12 python django django-models python-3.x on-delete
我阅读了有关PROTECT和RESTRICT 的django 文档,以与"on_delete"一起使用。
通过引发 ProtectedError(django.db.IntegrityError 的子类)来防止删除引用的对象。
例子:
class MyModel(models.Model):
field = models.ForeignKey(YourModel, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)
通过引发 RestrictedError (django.db.IntegrityError 的子类)来防止删除引用的对象。与 PROTECT 不同,如果引用的对象还引用了在同一操作中正在删除的不同对象,但通过 CASCADE 关系,则允许删除引用的对象。
例子:
class MyModel(models.Model):
field = models.ForeignKey(YourModel, on_delete=models.RESTRICT)
Run Code Online (Sandbox Code Playgroud)
在某种程度上,我可以理解PROTECT和RESTRICT之间的区别,但不完全理解PROTECT和RESTRICT之间的区别到底是什么?我什么时候应该使用它们?
Roh*_*ham 11
基于Django 文档 RESTRICT允许您在某些特殊情况下删除引用的对象。例如:
class Artist(models.Model):
name = models.CharField(max_length=10)
class Album(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
class Song(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.RESTRICT)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,如果您创建一个专辑实例,然后创建一个具有同一艺术家的歌曲实例(现在您有一首歌曲和一个具有同一艺术家的专辑),那么您可以简单地删除该艺术家而不会出现任何问题(因为在此删除操作中,您还将删除相关对象。另请注意,艺术家在歌曲和专辑删除上具有CASCADE 功能)。但如果您定义了PROTECT而不是RESTRICT,例如:
class Song(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)
您无法删除您的艺术家实例,因为该歌曲引用了该艺术家。如果你问我,我会说RESTRICT是PROTECT的另一个版本,对对象删除的限制较少。如果到目前为止这个解释还不清楚,我会推荐您 Django 示例本身:
即使这意味着删除Song引用的Album ,也可以删除Artist,因为Song还通过级联关系引用Artist本身。例如:
Run Code Online (Sandbox Code Playgroud)artist_one = Artist.objects.create(name='artist one') artist_two = Artist.objects.create(name='artist two') album_one = Album.objects.create(artist=artist_one) album_two = Album.objects.create(artist=artist_two) song_one = Song.objects.create(artist=artist_one, album=album_one) song_two = Song.objects.create(artist=artist_one, album=album_two) album_one.delete()
引发 RestrictedError。
Run Code Online (Sandbox Code Playgroud)artist_two.delete()
引发 RestrictedError。
Run Code Online (Sandbox Code Playgroud)artist_one.delete() (4, {'Song': 2, 'Album': 1, 'Artist': 1})
将成功删除您的对象
使用不同类型的on_delete实际上与您的设计和删除对象的限制有关。因此,基本上,当您只想保护对象不被删除(没有任何依赖项)时,使用PROTECT是最好的解决方案,因为在这种情况下使用RESTRICT,您会强制 Django 查看每个相关对象(嵌套的 for 循环)进行检查在此过程中是否会删除其他关系,可能会对您的删除性能产生不良影响。
小智 9
根据现实世界的应用需求,我们将两者用于不同的目的。
PROTECT 永远不会删除并引发错误。但是,RESTRICT(从 Django 3.1 引入)会在某些情况下删除,而不是全部。
PROTECT示例:
根据如何防止删除,
class Employee(models.Model):
name = models.CharField(name, unique=True)
class Project(models.Model):
name = models.CharField(name, unique=True)
employees = models.ForeignKey(Employee, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)
PROTECT解释:从现实世界的角度思考。会有很多Employees,并且一个Employee可以有多个Projects。如果我们删除一个Employee(如果他有多个Project与之关联的),模型中的项目对象Project将被保留。这是错误的。如果Employee做了任何Project事情,他(Employee对象)就不能被删除。因此我们使用了PROTECT. 这将有助于防止删除任何具有一个或多个与其关联的项目对象的 Employee 对象。
在理解之前你需要CASCADE先理解RESTRICT:
CASCADE例子:
class Artist(models.Model):
name = models.CharField(max_length=10)
class Album(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)
CASCADE解释:从现实世界的角度思考。会有很多Artists,并且一个Artist可以有多个Albums。如果我们想删除一个Artist和他/她相关的Albums,我们将使用CASCADE. 记住,CASCADE删除。它总是删除。
RESTRICT例子:
class Artist(models.Model):
name = models.CharField(max_length=10)
class Album(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
class Song(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.RESTRICT)
Run Code Online (Sandbox Code Playgroud)
RESTRICT解释:现在,再从现实世界的角度思考一下。AnArtist将有零个或多个Albums。AnAlbum可以有零个或多个Songs。Artist如果an有0个Album,anAlbum有0个,删除是没有问题的Song。事实上,没有任何关系,因为根本Artist没有任何s。当 an具有多个s 并且 an具有多个sAlbum时,就会出现删除问题并且场景开始。就是这样:ArtistAlbumAlbumSong
RESTRICT并且PROTECT以同样的方式工作。但是,保护分为两个步骤。父母和孩子。如果我们不应该删除 Child ( Album),那么我们也不应该删除 Parent ( Artist)。换句话说,如果我们不想删除PROTECTParent(),则使用 if 我们不希望 Child ( ) 被删除。防止删除对象。AlbumArtistPROTECT
并且,RESTRICT分为三个步骤。父母和孩子以及孙子。RESTRICT(限制条件或措施)仅限制删除对象达到一定限度。
您需要了解我们为什么使用的现实世界场景RESTRICT。假设有多个Artists。每个Artists 有多个Albums。每个Album都有多个songs。看下面的代码
>>> artist_one = Artist.objects.create(name='artist one')
>>> artist_two = Artist.objects.create(name='artist two')
>>> album_one = Album.objects.create(artist=artist_one)
>>> album_two = Album.objects.create(artist=artist_two)
>>> song_one = Song.objects.create(artist=artist_one, album=album_one)
>>> song_two = Song.objects.create(artist=artist_one, album=album_two)
>>> album_one.delete()
# Raises RestrictedError.
>>> artist_two.delete()
# Raises RestrictedError.
>>> artist_one.delete()
(4, {'Song': 2, 'Album': 1, 'Artist': 1})
Run Code Online (Sandbox Code Playgroud)
请注意,从上面的代码来看,
song_one和song_two来自相同的s Artist,不同的Albums 来自不同的Artists。song可以由一个或多个人演唱/创作/分享。ArtistSong可以在许多Album歌曲中由一个或多个Artist歌曲演唱/创作。Album包含许多Song由不同人演唱/创作的歌曲Artist。工作原理RESTRICTS:
现在,在现实世界中,如果我们必须删除Artist他的所有Albums 和Songs 中的 sAlbum都应该被删除。但是,只有当他的s中的所有歌曲Album都不与其他artists共享关系时。换句话说,当所有歌曲都引用相同的 时,就会发生、s 和sArtist的删除。ArtistAlbumSong
请注意,我们无法删除artist_two,因为与song_two共享了他。album_twoartist_one
简单来说,在Song对象中,如果artist和artist专辑中的内容相同,RESTRICT允许删除。
用简单的话来说,简短的答案是:
CASCADE通过删除父项,子项也会被删除。
SET_NULL让父级被删除但保留子级。
PROTECT永远不要让父项的删除导致子项的删除。
whileRESTRICT仅当其所有所有者(父级)在过去或当前被删除时才允许删除子级(RESTRICT确保其他实例的属性中没有子级实例)。
| 归档时间: |
|
| 查看次数: |
8176 次 |
| 最近记录: |