我对Django相当熟悉,但我最近注意到这些型号有on_delete=models.CASCADE个选项.我已经搜索了相同的文档,但我找不到比以下内容更多的信息:

Changed in Django 1.9:

on_delete现在可以用作第二个位置参数(以前它通常只作为关键字参数传递).在Django 2.0中,它将是必需的参数.

An example case of usage is:

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...

class Manufacturer(models.Model):
    # ...
    pass

on_delete做什么?(I guess the actions to be done if the model is deleted.)

models.CASCADE是做什么的?(any hints in documentation)

还有哪些选项可用(if my guess is correct)?

这方面的文档存放在哪里?

推荐答案

这是删除referenced对象时要采用的行为.这不是Django特有的;这是一个SQL标准.尽管Django在SQL之上有自己的实现.(1)

发生此类事件时,可采取七种可能的操作:

  • CASCADE:删除被引用的对象时,也要删除对其有引用的对象(例如,当你删除一篇博客文章时,你可能也想删除 comments ).SQL等效值:CASCADE.
  • PROTECT:禁止删除被引用的对象.要删除它,您必须手动删除引用它的所有对象.SQL类似功能:RESTRICT.
  • RESTRICT:(introduced in Django 3.1)PROTECT类似的行为,更精确地匹配SQL的RESTRICT.(见django documentation example)
  • SET_NULL:将引用设置为NULL(要求字段可为NULL).例如,当你删除一个用户时,你可能想保留他在博客帖子上发表的 comments ,但说它是由一个匿名(或已删除)用户发布的.SQL类似功能:SET NULL.
  • SET_DEFAULT:设置默认值.SQL类似功能:SET DEFAULT.
  • SET(...):设置一个给定的值.这不是SQL标准的一部分,完全由Django处理.
  • DO_NOTHING:这可能是一个非常糟糕的主意,因为这会在数据库中产生完整性问题(引用实际上不存在的对象).SQL类似功能:NO ACTION.(2)

资料来源:Django documentation

例如,参见the documentation of PostgreSQL.

在大多数情况下,CASCADE是预期的行为,但对于每一个 foreign 人,你应该始终问自己在这种情况下预期的行为是什么.PROTECTSET_NULL通常很有用.如果不应该设置CASCADE,只需删除一个用户,就可以级联删除所有数据库.


Additional note to clarify cascade direction

有趣的是,注意到CASCADE行动的方向对许多人来说并不清楚.实际上,有趣的是注意到onlyCASCADE的动作并不清楚.我理解级联行为可能会令人困惑,但是您必须考虑到it is the same direction as any other action.所以,如果你觉得CASCADE的方向你不清楚,其实就是on_delete的行为你不清楚.

在您的数据库中,外键基本上由一个整型字段表示,该值是外键的主键.假设您有一个条目comment_A,它具有指向条目article_B的外键.如果删除条目comment_A,则一切正常.article_B过go 没有comment_A也活着,如果被删除了也不用费心了.但是,如果你删掉article_B,那么comment_A就会panic !它从来没有离开过article_B并且需要它,而且它是它的属性的一部分(article=article_B,但是article_B是什么呢?).这就是on_delete个步骤,以确定如何解决这个integrity error问题,方法是说:

  • "No! Please! Don't! I can't live without you!"(在Django/SQL中表示为PROTECTRESTRICT)
  • "All right, if I'm not yours, then I'm nobody's"(也就是说SET_NULL)
  • "Good bye world, I can't live without article_B"然后自杀(这是CASCADE的行为).
  • "It's OK, I've got spare lover, and I'll reference article_C from now"(SET_DEFAULT,甚至SET(...)).
  • "I can't face reality, and I'll keep calling your name even if that's the only thing left to me!" (DO_NOTHING)

我希望这能让cascade的方向更清晰.:)


Footnotes

(1) Django在SQL之上有自己的实现.而且,作为mentioned by @JoeMjr2 in the comments below,Django将不会创建SQL约束.如果您希望数据库确保约束(例如,如果您的数据库由另一个应用程序使用,或者如果您经常挂起数据库控制台),您可能希望自己手动设置相关的约束.在Django中有an open ticket个要添加对删除约束的数据库级别的支持.

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

Python相关问答推荐

如何在vercel中指定Python运行时版本?

使用Beautiful Soup获取第二个srcset属性

使用Python Cerberus初始化一个循环数据 struct (例如树)(v1.3.5)

过滤绕轴旋转的螺旋桨

覆盖Django rest响应,仅返回PK

计算相同形状的两个张量的SSE损失

Python在tuple上操作不会通过整个单词匹配

Pydantic 2.7.0模型接受字符串日期时间或无

根据另一列中的nan重置值后重新加权Pandas列

Pytest两个具有无限循环和await命令的Deliverc函数

运行总计基于多列pandas的分组和总和

在Wayland上使用setCellWidget时,try 编辑QTable Widget中的单元格时,PyQt 6崩溃

如何请求使用Python将文件下载到带有登录名的门户网站?

如何获得每个组的时间戳差异?

如何调整QscrollArea以正确显示内部正在变化的Qgridlayout?

关于Python异步编程的问题和使用await/await def关键字

ThreadPoolExecutor和单个线程的超时

如何在BeautifulSoup/CSS Select 器中处理regex?

如何使用使用来自其他列的值的公式更新一个rabrame列?

Polars Group by描述扩展