小编典典

on_delete 对 Django 模型有什么作用?

all

我对 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?( 文档中的任何提示

还有哪些其他选项可用( 如果我的猜测是正确的 )?

这方面的文档在哪里?


阅读 107

收藏
2022-03-06

共1个答案

小编典典

这是删除引用 对象时要采用的行为。它不是特定于 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 曾经没有 评论_A
生活,如果它被删除也不要打扰。但是,如果您删除 article_B ,那么 comment_A 就会出现恐慌!它从来没有没有
article_B 并且需要它,它是它的属性的一部分(article=article_B但是 article_B
是什么???)。这是介入的地方on_delete,以确定如何解决这个问题 完整性错误 ,或者说:

  • “不!求你了!不要!没有你我​​活不下去!” (在 Django/SQL中说PROTECT或)RESTRICT
  • “好吧,如果我不是你的,那么我就不是任何人的” (据说SET_NULL
  • “再见世界,我不能没有文章_B” 并自杀(这是CASCADE行为)。
  • “没关系,我有多余的爱人,从现在开始我会参考article_C”SET_DEFAULT,甚至SET(...))。
  • “我无法面对现实,我会一直呼唤你的名字,即使那是我唯一的事情!” ( DO_NOTHING)

我希望它使级联方向更清晰。:)


脚注

(1) Django 在 SQL 之上有自己的实现,Django 不会创建SQL约束。如果您希望数据库确保约束(例如,如果您的数据库被另一个应用程序使用,或者如果您不时挂在数据库控制台中),您可能需要自己手动设置相关约束。在Django
中添加对删除约束的数据库级支持的开放票。

(2) 实际上,有一种情况DO_NOTHING可能有用:如果您想跳过 Django 的实现并在数据库级别自己实现约束。

2022-03-06