on_delete 对 Django 模型有什么作用? [英] What does on_delete do on Django models?

查看:32
本文介绍了on_delete 对 Django 模型有什么作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Django 非常熟悉,但我最近注意到模型中有一个 on_delete=models.CASCADE 选项.我已经搜索了相同的文档,但我找不到比以下内容更多的内容:

<块引用>

在 Django 1.9 中更改:

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

使用示例是:

from django.db 导入模型类汽车(模型.模型):制造商 = 模型.ForeignKey('制造商',on_delete=models.CASCADE,)# ...类制造商(模型.模型):# ...经过

on_delete 有什么作用?(我猜删除模型后要执行的操作.)

models.CASCADE 有什么作用?(文档中的任何提示)

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

这方面的文档在哪里?

解决方案

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

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

  • CASCADE:当引用的对象被删除时,也删除引用它的对象(例如,当您删除博客文章时,您可能还想删除评论).SQL 等效项:CASCADE.
  • PROTECT:禁止删除引用的对象.要删除它,您必须手动删除所有引用它的对象.SQL 等效项:RESTRICT.
  • RESTRICT:(在 Django 3.1 中引入)PROTECT 类似的行为,更准确地匹配 SQL 的 RESTRICT.(参见 django 文档示例)
  • SET_NULL:将引用设置为 NULL(要求字段可以为空).例如,当您删除一个用户时,您可能希望保留他在博客文章上发表的评论,但假设它是由匿名(或已删除)用户发表的.SQL 等效项:SET NULL.
  • SET_DEFAULT:设置默认值.SQL 等效项:SET DEFAULT.
  • SET(...):设置给定值.这不是 SQL 标准的一部分,完全由 Django 处理.
  • DO_NOTHING:可能是一个非常糟糕的主意,因为这会在您的数据库中造成完整性问题(引用一个实际上不存在的对象).SQL 等效项:NO ACTION.(2)

来源:Django 文档

例如,另请参见PostgreSQL 文档.

在大多数情况下,CASCADE 是预期的行为,但对于每个外键,您应该始终问自己在这种情况下的预期行为是什么.PROTECTSET_NULL 通常很有用.将 CASCADE 设置在不应该的位置,可能会通过简单地删除单个用户来潜在地删除所有数据库.


澄清级联方向的附加说明

有趣的是,CASCADE 动作的方向对很多人来说并不清楚.实际上,有趣的是注意到 CASCADE 操作不清楚.我知道级联行为可能会令人困惑,但是您必须认为它与任何其他操作的方向相同.所以,如果你觉得CASCADE的方向不清楚,那其实就是你不清楚on_delete的行为.

在您的数据库中,外键基本上由一个整数字段表示,该字段的值是外对象的主键.假设您有一个条目 comment_A,它有一个条目 article_B 的外键.如果您删除条目 comment_A,则一切正常.article_B 过去没有comment_A,如果它被删除了也不要打扰.但是,如果您删除文章_B,则评论_A 会发生恐慌!它从来都离不开article_B 并且需要它,这是其属性的一部分(article=article_B,但什么是article_B???).这是 on_delete 介入的地方,以确定如何解决这个完整性错误,或者说:

  • "不!请!别!没有你我活不下去!"(在 Django/SQL 中被称为 PROTECTRESTRICT)
  • 好吧,如果我不是你的,那我就是别人的"(也就是SET_NULL)
  • 再见世界,我不能没有文章_B"并自杀(这是CASCADE行为).
  • 没关系,我有闲人,从现在开始我会参考文章_C"(SET_DEFAULT,甚至SET(...)).
  • 我无法面对现实,我会继续呼唤你的名字,即使这是我唯一剩下的事情!" (DO_NOTHING)

我希望它能让级联方向更清晰.:)


脚注

<块引用>

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

<块引用>

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

I'm quite familiar with Django, but I recently noticed there exists an on_delete=models.CASCADE option with the models. I have searched for the documentation for the same, but I couldn't find anything more than:

Changed in Django 1.9:

on_delete can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in 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

What does on_delete do? (I guess the actions to be done if the model is deleted.)

What does models.CASCADE do? (any hints in documentation)

What other options are available (if my guess is correct)?

Where does the documentation for this reside?

解决方案

This is the behaviour to adopt when the referenced object is deleted. It is not specific to Django; this is an SQL standard. Although Django has its own implementation on top of SQL. (1)

There are seven possible actions to take when such event occurs:

  • 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)

Source: Django documentation

See also the documentation of PostgreSQL for instance.

In most cases, CASCADE is the expected behaviour, but for every ForeignKey, you should always ask yourself what is the expected behaviour in this situation. PROTECT and SET_NULL are often useful. Setting CASCADE where it should not, can potentially delete all of your database in cascade, by simply deleting a single user.


Additional note to clarify cascade direction

It's funny to notice that the direction of the CASCADE action is not clear to many people. Actually, it's funny to notice that only the CASCADE action is not clear. I understand the cascade behavior might be confusing, however you must think that it is the same direction as any other action. Thus, if you feel that CASCADE direction is not clear to you, it actually means that on_delete behavior is not clear to you.

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, and 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:

  • "No! Please! Don't! I can't live without you!" (which is said PROTECT or RESTRICT in Django/SQL)
  • "All right, if I'm not yours, then I'm nobody's" (which is said SET_NULL)
  • "Good bye world, I can't live without article_B" and commit suicide (this is the CASCADE behavior).
  • "It's OK, I've got spare lover, and I'll reference article_C from now" (SET_DEFAULT, or even 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)

I hope it makes cascade direction clearer. :)


Footnotes

(1) Django has its own implementation on top of SQL. And, as mentioned by @JoeMjr2 in the comments below, Django will not create the SQL constraints. If you want the constraints to be ensured by your database (for instance, if your database is used by another application, or if you hang in the database console from time to time), you might want to set the related constraints manually yourself. There is an open ticket to add support for database-level on delete constrains in Django.

(2) Actually, there is one case where DO_NOTHING can be useful: If you want to skip Django's implementation and implement the constraint yourself at the database-level.

这篇关于on_delete 对 Django 模型有什么作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆