我很熟悉Django,但我最近注意到存在一个on_delete=models。级联选项与模型。我已经搜索了相同的文档,但我找不到更多的东西:

在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做什么?(我猜如果模型被删除了要做的动作。)

什么是模型。级联做什么?(文档中的提示)

还有什么其他的选择(如果我的猜测是正确的)?

这方面的文档放在哪里?


当前回答

删除父对象时删除数据库中的所有子字段,然后使用on_delete,如下所示:

class user(models.Model):
    commodities = models.ForeignKey(commodity, on_delete=models.CASCADE)

其他回答

重新定位你对“CASCADE”功能的思维模式,将FK添加到一个已经存在的CASCADE(即瀑布)中。这个瀑布的源是一个主键(PK)。删除向下流动。

因此,如果您将一个FK的on_delete定义为“CASCADE”,那么您将把这个FK的记录添加到一个源于PK的级联删除中。FK的记录可能参与这个级联,也可能不参与(“SET_NULL”)。事实上,具有FK的记录甚至可能阻止删除流!用“PROTECT”建造一座大坝。

简单地说,on_delete是一条指令,用于指定在删除外部对象时将对对象进行哪些修改:

CASCADE:当外部对象被删除时,将删除子对象

SET_NULL:将子对象外键设置为null

SET_DEFAULT:在创建模型时将子对象设置为给定的默认数据

RESTRICT:在某些条件下引发RestrictedError。

PROTECT:防止外部对象被删除,只要有子对象从它继承

额外的链接:

https://docs.djangoproject.com/en/4.0/ref/models/fields/#foreignkey

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

当此类事件发生时,可以采取7种措施:

CASCADE: When the referenced object is deleted, also delete the objects that have references to it (when you remove a blog post for instance, you might want to delete comments as well). SQL equivalent: CASCADE. PROTECT: Forbid the deletion of the referenced object. To delete it you will have to delete all objects that reference it manually. SQL equivalent: RESTRICT. RESTRICT: (introduced in Django 3.1) Similar behavior as PROTECT that matches SQL's RESTRICT more accurately. (See django documentation example) SET_NULL: Set the reference to NULL (requires the field to be nullable). For instance, when you delete a User, you might want to keep the comments he posted on blog posts, but say it was posted by an anonymous (or deleted) user. SQL equivalent: SET NULL. SET_DEFAULT: Set the default value. SQL equivalent: SET DEFAULT. SET(...): Set a given value. This one is not part of the SQL standard and is entirely handled by Django. DO_NOTHING: Probably a very bad idea since this would create integrity issues in your database (referencing an object that actually doesn't exist). SQL equivalent: NO ACTION. (2)

来源:Django文档

例如,请参阅PostgreSQL的文档。

在大多数情况下,CASCADE是预期的行为,但对于每个ForeignKey,你应该总是问自己在这种情况下预期的行为是什么。PROTECT和SET_NULL通常很有用。在不应该的地方设置CASCADE,只需删除单个用户,就可以潜在地级联删除所有数据库。


澄清级联方向的附加说明

有趣的是,许多人都不清楚CASCADE动作的方向。实际上,有趣的是,只有CASCADE动作是不清楚的。我知道级联行为可能会让人困惑,但你必须认为它与任何其他行为的方向相同。因此,如果您觉得CASCADE方向不清楚,这实际上意味着on_delete行为不清楚。

In your database, a foreign key is basically represented by an integer field which value is the primary key of the foreign object. Let's say you have an entry comment_A, which has a foreign key to an entry article_B. If you delete the entry comment_A, everything is fine. article_B used to live without comment_A and don't bother if it's deleted. However, if you delete article_B, then comment_A panics! It never lived without article_B and needs it, it's part of its attributes (article=article_B, but what is article_B???). This is where on_delete steps in, to determine how to resolve this integrity error, either by saying:

“不!拜托!不!我不能没有你!”(在Django/SQL中是PROTECT或RESTRICT) “好吧,如果我不是你的,那我就不是任何人的”(SET_NULL) “再见世界,我不能没有article_B”然后自杀(这是CASCADE行为)。 “没关系,我有一个备用情人,我将从现在开始引用article_C”(SET_DEFAULT,甚至SET(…))。 “我无法面对现实,我会一直叫你的名字,即使那是我唯一剩下的东西!”(DO_NOTHING)

我希望它能让瀑布方向更清晰。:)


脚注

Django在SQL之上有自己的实现。并且,正如下面@JoeMjr2在评论中提到的,Django不会创建SQL约束。如果您希望数据库确保约束(例如,如果您的数据库由另一个应用程序使用,或者您不时挂在数据库控制台中),您可能希望自己手动设置相关的约束。在Django中增加对数据库级删除约束的支持是开放的。

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

删除父对象时删除数据库中的所有子字段,然后使用on_delete,如下所示:

class user(models.Model):
    commodities = models.ForeignKey(commodity, on_delete=models.CASCADE)

CASCADE也会删除与之相连的对应字段。