on_delete对Django模型有什么作用?

发布于 2021-01-29 16:28:32

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

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

有关此文档的位置在哪里?

关注者
0
被浏览
43
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这是删除 引用 对象时采取的行为。它不是特定于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确定如何解决此问题的步骤 完整性错误 ,可以这样说:

    • “不!请!不要!我不能没有你!” (据说PROTECTRESTRICT在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的实现并自己在数据库级别实现约束。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看