我对Django非常熟悉,但最近注意到模型中存在 on_delete=models.CASCADE
选项,我搜索了相同的文档,但找不到更多:
在Django 1.9中更改:on_delete现在可以用作第二个位置参数(以前它通常只作为关键字参数传递) . 它将是Django 2.0中的必需参数 .
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
on_delete做什么? (我猜想删除模型时要采取的措施)
models.CASCADE
做什么? (文档中的任何提示)
还有哪些其他选择(如果我的猜测是正确的)?
这个文档在哪里?
5 回答
这是删除引用对象时要采用的行为 . 它不是django特有的,这是一个SQL标准 .
发生此类事件时,有6种可能的操作:
CASCADE
:删除引用的对象时,也删除引用它的对象(例如,当您删除博客文章时,您可能也想删除注释) . SQL等价物:CASCADE
.PROTECT
:禁止删除引用的对象 . 要删除它,您必须删除手动引用它的所有对象 . SQL等价物:RESTRICT
.SET_NULL
:将引用设置为NULL(要求字段可以为空) . 例如,当您删除用户时,您可能希望保留他在博客帖子上发布的评论,但是说它是由匿名(或已删除)用户发布的 . SQL等价物:SET NULL
.SET_DEFAULT
:设置默认值 . SQL等价物:SET DEFAULT
.SET(...)
:设置给定值 . 这个不是SQL标准的一部分,完全由Django处理 .DO_NOTHING
:可能是一个非常糟糕的主意,因为这会在数据库中创建完整性问题(引用实际上不存在的对象) . SQL等价物:NO ACTION
.资料来源:Django documentation
例如,参见the documentation of PostGreSQL .
在大多数情况下,
CASCADE
是预期的行为,但是对于每个ForeignKey,您应该总是问自己在这种情况下的预期行为是什么 .PROTECT
和SET_NULL
通常很有用 . 将CASCADE
设置为不应该,可以通过简单地删除单个用户来潜在地删除所有数据库 .on_delete
方法用于告诉Django如何处理依赖于您删除的模型实例的模型实例 . (例如ForeignKey
关系) .on_delete=models.CASCADE
告诉Django级联删除效果,即继续删除依赖模型 .这是一个更具体的例子 . 假设_846259_模型中的
Author
模型是ForeignKey
. 现在,如果删除Author
模型的实例,Django将不知道如何处理依赖于Author
模型实例的Book
模型的实例 .on_delete
方法告诉Django在这种情况下该怎么做 . 设置on_delete=models.CASCADE
将指示Django级联删除效果,即删除依赖于您删除的Author
模型实例的所有Book
模型实例 .Note: on_delete will become a required argument in Django 2.0. In older versions it defaults to CASCADE.
Here's the entire official documentation.
仅供参考,模型中的on_delete参数是从它听起来的倒退 . 您将“on_delete”放在模型上的外键(FK)上,告诉django如果删除了您在记录中指向的FK条目该怎么做 . 我们的商店最常用的选项是PROTECT,CASCADE和SET_NULL . 以下是我发现的基本规则:
当你的FK指向一个真正不应该改变的查找表时,请使用PROTECT,这肯定不会导致你的表发生变化 . 如果有人试图删除该查找表上的条目,PROTECT会阻止它们删除它,如果它与任何记录绑定 . 它还可以防止django删除您的记录,因为它删除了查找表中的条目 . 最后一部分至关重要 . 如果有人要从我的性别表中删除性别"Female",我绝不希望立即删除我在Person表中拥有该性别的所有人 .
当FK指向"parent"记录时使用CASCADE . 因此,如果一个人可以拥有许多PersonEthnicity条目(他/她可以是美洲印第安人,黑人和白人),并且该人被删除,我真的希望删除任何"child" PersonEthnicity条目 . 没有这个人,他们是无关紧要的 .
如果您希望允许人们删除查找表中的条目,但仍希望保留您的记录,请使用SET_NULL . 例如,如果一个人可以拥有一个HighSchool,但是如果那个高中学校在我的查找表上消失对我来说并不重要,我会说"on_delete=SET_NULL."这会留下我的人员记录;它只是将我的Person上的高中FK设置为null . 显然,你必须在FK上允许null = True .
以下是完成所有三件事的模型示例:
作为最后的花絮,你知道吗,如果你不指定on_delete(或没有),默认行为是CASCADE?这意味着,如果有人在您的性别表中删除了性别条目,那么任何具有该性别的人员记录也会被删除!
我会说,“如果有疑问,请设置on_delete = models.PROTECT . ”然后去测试你的应用程序 . 您将很快找出哪些FK应该标记其他值而不会危及您的任何数据 .
此外,值得注意的是,on_delete = CASCADE实际上未添加到任何迁移中,如果这是您选择的行为 . 我想这是因为它是默认值,所以把on_delete = CASCADE与什么都不做是一回事 .
如前所述,CASCADE将删除具有外键的记录并引用已删除的另一个对象 . 例如,如果您有一个房地产网站并且拥有引用城市的房产
现在当从数据库中删除城市时,所有相关的属性(例如位于该城市的房地产)也将从数据库中删除
现在我还想提一下其他选项的优点,比如SET_NULL或SET_DEFAULT,甚至DO_NOTHING . 基本上,从管理角度来看,您希望“删除”这些记录 . 但你真的不希望它们消失 . 因为许多的原因 . 有人可能会意外删除它,或者用于审计和监视 . 而且报道很简单 . 因此,它可以是一种将房产与城市“断开”的方式 . 同样,它将取决于您的应用程序的编写方式 .
例如,某些应用程序的字段"deleted"为0或1.所有搜索和列表视图等,可以出现在报表中的任何内容或用户可以从前端访问的任何内容,都会排除
deleted == 1
的所有内容 . 但是,如果您创建自定义报告或自定义查询以下拉已删除的记录列表,甚至更多以查看上次修改的时间(另一个字段)以及由谁(即谁删除它以及何时删除) . 从行政角度来看,这是非常有利的 .并且不要忘记,对于那些记录,您可以像
deleted = 0
一样简单地恢复意外删除 .我的观点是,如果有功能,总有一个原因 . 并不总是一个很好的理由 . 但原因 . 而且往往也是一个好人 .
Here is answer for your question that says: why we use on_delete?
删除ForeignKey引用的对象时,Django默认模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象 . 可以通过指定on_delete参数来覆盖此行为 . 例如,如果您有一个可为空的ForeignKey,并且希望在删除引用的对象时将其设置为null:
The possible values for on_delete are found in django.db.models:
CASCADE: 级联删除;默认 .
PROTECT: 通过引发ProtectedError(django.db.IntegrityError的子类)来防止删除引用的对象 .
SET_NULL: 设置ForeignKey为null;这只有在null为True时才有可能 .
SET_DEFAULT: 将ForeignKey设置为其默认值;必须设置ForeignKey的默认值 .