on_delete对Django模型有什么作用?
我对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
办?( 文档中的任何提示 )
还有哪些其他选项( 如果我的猜测是正确的 )?
有关此文档的位置在哪里?
-
这是删除 引用 对象时采取的行为。它不是特定于Django的。这是一个SQL标准。尽管Django在SQL之上有自己的实现。 (1)
发生此类事件时,有七种可能的操作:
CASCADE
:删除引用的对象后,还请删除对其具有引用的对象(例如,当删除博客文章时,您可能还希望删除注释)。SQL等效项:CASCADE
。PROTECT
:禁止删除引用的对象。要删除它,您将必须删除所有手动引用它的对象。SQL等效项:RESTRICT
。RESTRICT
:( 在Django 3.1中引入)PROTECT
与SQLRESTRICT
更精确匹配的相似行为。(请参阅django文档示例)SET_NULL
:将引用设置为NULL(要求该字段可为空)。例如,当删除用户时,您可能希望保留他在博客文章中发布的评论,但说该评论是由匿名(或已删除)用户发布的。SQL等效项:SET NULL
。SET_DEFAULT
:设置默认值。SQL等效项:SET DEFAULT
。SET(...)
:设置给定值。这不是SQL标准的一部分,完全由Django处理。DO_NOTHING
:这可能是一个非常糟糕的主意,因为这会在数据库中创建完整性问题(引用实际上不存在的对象)。SQL等效项:NO ACTION
。 (2)
资料来源:Django说明文件
例如,另请参见PostgreSQL文档。
在大多数情况下,这
CASCADE
是预期的行为,但是对于每个ForeignKey,您应始终问自己在这种情况下的预期行为是什么。PROTECT
并且SET_NULL
通常很有用。设置CASCADE
不应该设置的位置,可以通过简单地删除单个用户来级联删除所有数据库。
附加说明以阐明级联方向
有趣的是,注意到
CASCADE
行动的方向对于许多人来说并不明确。事实上,这很有趣地看到, 只有
该CASCADE
行动并不清楚。我知道级联行为可能会造成混淆,但是您必须认为 它与任何其他动作是同一方向
。因此,如果您觉得自己CASCADE
不清楚方向,那实际上意味着on_delete
您不清楚自己的行为。在您的数据库中,外键基本上由整数字段表示,该值是外对象的主键。假设您有一个 comment_A 条目,它具有一个 article_B
条目的外键。如果删除条目 comment_A ,那么一切都很好。 article_B 过去一直没有 comment_A
,如果删除了它,也不会打扰。但是,如果您删除 article_B ,那么 comment_A会 慌!它永远都离不开
article_B 并需要它,它是其属性的一部分(article=article_B
,但 article_B
是什么?)。这是on_delete
确定如何解决此问题的步骤 完整性错误 ,可以这样说:- “不!请!不要!我不能没有你!” (据说
PROTECT
或RESTRICT
在Django / SQL中) - “好吧,如果我不是你的,那我就不是任何人的” (说
SET_NULL
) - “再见,我不能没有article_B生活” 自杀(这是
CASCADE
行为)。 - “没关系,我有多余的情人,从现在开始我将引用article_C” (
SET_DEFAULT
,甚至SET(...)
)。 - “我无法面对现实,即使那是我剩下的唯一事情,我也会继续给你打电话!” (
DO_NOTHING
)
我希望它使级联方向更清晰。:)
脚注
(1) Django在SQL之上有自己的实现。并且,正如@
JoeMjr2在下面的注释中提到的那样,Django将不会创建SQL约束。如果希望数据库确保约束(例如,如果数据库被其他应用程序使用,或者您不时挂在数据库控制台中),则可能需要自己手动设置相关约束。在Django中,有一个开放式票证可添加对数据库级别的删除约束的支持。(2) 实际上,在一种情况下
DO_NOTHING
可能有用:如果您想跳过Django的实现并自己在数据库级别实现约束。