简体   繁体   English

为什么Django会对外键进行级联删除?

[英]Why does Django do cascading deletes on foreign keys?

Django does a cascading delete on models with foreign keys as a default. Django在具有外键的模型上进行级联删除作为默认值。 That is, say you have a ForeignKey in A pointing to B, and you delete B, then A will be deleted as well. 也就是说,假设您在A中有一个指向B的ForeignKey,并且您删除了B,那么A也将被删除。

This is known and documented , but I haven't found any good rationale for the design decision around making it a default, given how unintuitive it seems. 这是众所周知的 ,但是我没有找到任何关于将其作为默认设计决策的合理理由,因为它看起来有多么不直观。 Does anyone know why it may be the case? 有谁知道为什么会这样?

7 Years ago... 7年前......

a Ticket was open #7539 门票开放#7539

Where it began to be discussed. 它开始被讨论的地方。

years ago by benjaoming 几年前由benjaoming

Someone requested a discussion... I just had an encounter with this, and what I lacked was knowing what's going on with regards to cascading deletion, because it's quite dangerous (you loose data!!) and steals lots of time. 有人请求讨论......我刚刚遇到了这个问题,我缺少的是知道关于级联删除的问题,因为它非常危险(你丢失数据!!)并且窃取了大量时间。 Preventing it is simple, though. 但是,预防它很简单。 Overriding the delete() method of a model and calling clear() on the related model's foreign keys is simple, and it's a manual implementation, that all programmers should be able to understand. 覆盖模型的delete()方法并在相关模型的外键上调用clear()很简单,它是一个手动实现,所有程序员都应该能够理解。 But I can think of another alternative: If null=True for the foreign key in question, why not automatically use SET NULL when the related instance is deleted? 但我可以想到另一种选择:如果有问题的外键,如果null = True,为什么在删除相关实例时不自动使用SET NULL? For me, this is even more "intuitive" than CASCADE. 对我来说,这比CASCADE更“直观”。 After all, null=True is something that the programmer specifies and has to deal with anywhere in the implementation, which is also why he doesn't need cascading deletion of such a relation. 毕竟,null = True是程序员指定并且必须在实现中的任何地方处理的东西,这也是他不需要级联删除这种关系的原因。 Also, if on_delete is possible to set in a key field, it would have to comply with the null option.. and together with the "intuition argument" that creates a 1:1 correspondence between the two options. 此外,如果on_delete可以在键字段中设置,则必须符合null选项..并与“intuition argument”一起创建两个选项之间的1:1对应关系。 And then the "logic argument": Django handles its logic in Python code, not in the Database, which is kept as a simple storage engine. 然后是“逻辑参数”:Django在Python代码中处理它的逻辑,而不是在数据库中处理它,数据库被保存为一个简单的存储引擎。 The RESTRICT option is a validation issue, and will probably be handled this way in most cases, so having the database enforcing it, would be redundant. RESTRICT选项是一个验证问题,在大多数情况下可能会以这种方式处理,因此让数据库强制执行它会是多余的。 To enable it on model-level could pave the way for some nice new automatic validation in ModelForms, so I think it sounds like a nice feature. 在模型级别启用它可以为ModelForms中的一些不错的新自动验证铺平道路,所以我认为这听起来像一个很好的功能。 If all this is implemented, I would suggest to remove the null option from key fields and have it set according to on_delete. 如果实现了所有这些,我建议从关键字段中删除null选项,并根据on_delete设置它。

Years later, the matter was again discussed in the group. 多年以后,该小组再次讨论了这个问题。

Django developers (Contributions to Django itself) Django开发人员(对Django本身的贡献)
changing the on_delete=CASCADE default 更改on_delete = CASCADE默认值

And then other tickets were created #21127 and #21961 . 然后其他的票被创造 #21127#21961

And we got here. 我们到了这里。 ForeignKey and OneToOneField on_delete argument ForeignKey和OneToOneField on_delete参数

In order to increase awareness about cascading model deletion, the on_delete argument of ForeignKey and OneToOneField will be required in Django 2.0. 为了提高对级联模型删除的认识,在Django 2.0中将需要ForeignKey和OneToOneField的on_delete参数。

Update models and existing migrations to explicitly set the argument. 更新模型和现有迁移以显式设置参数。 Since the default is models.CASCADE, add on_delete=models.CASCADE to all ForeignKey and OneToOneFields that don't use a different option. 由于默认值为models.CASCADE,因此将on_delete = models.CASCADE添加到不使用其他选项的所有ForeignKey和OneToOneField。 You can also pass it as the second positional argument if you don't care about compatibility with older versions of Django. 如果你不关心与旧版Django的兼容性,你也可以将它作为第二个位置参数传递。

There is a fairly lengthy discussion on this in this ticket . 这张票中有一个相当冗长的讨论。 In Django 2.0 the on_delete argument will be required so the current default behaviour will no longer apply. 在Django 2.0中, 将需要 on_delete参数,因此将不再应用当前的默认行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM