为啥 Django 对外键进行级联删除?
Posted
技术标签:
【中文标题】为啥 Django 对外键进行级联删除?【英文标题】:Why does Django do cascading deletes on foreign keys?为什么 Django 对外键进行级联删除? 【发布时间】:2015-12-23 22:59:19 【问题描述】:Django 默认使用外键对模型进行级联删除。也就是说,假设你在 A 中有一个 ForeignKey 指向 B,你删除了 B,那么 A 也会被删除。
This is known and documented,但考虑到它看起来多么不直观,我还没有找到任何好的理由来决定将其设为默认值。有谁知道为什么会这样?
【问题讨论】:
我相信这是因为如果他的依赖不存在,那么依赖于其他的对象就不能存在。这是依赖对象存在的需求关系。从软件中获取,如果所有依赖项都不存在,程序就无法运行,对吧? 为什么要在默认情况下保留相关记录?大多数情况下,当您删除父记录时,不需要子记录。 【参考方案1】:7 年前...
票已打开#7539
开始讨论的地方。
几年前,本杰明
有人要求讨论...我刚遇到这个, 而我缺乏的是知道关于发生了什么 级联删除,因为它非常危险(您丢失数据!) 并偷走了很多时间。不过,防止它很简单。覆盖 模型的 delete() 方法并在相关模型上调用 clear() 模型的外键很简单,是手动实现的, 所有的程序员都应该能够理解。但我能想到 另一种选择:如果所讨论的外键为 null=True,为什么 删除相关实例时不会自动使用 SET NULL 吗? 对我来说,这比 CASCADE 更“直观”。毕竟, null=True 是程序员指定并且必须处理的东西 在实施中的任何地方,这也是他不需要的原因 级联删除这种关系。此外,如果 on_delete 是可能的 要在关键字段中设置,它必须符合 null 选项.. 并与创建 1:1 的“直觉论证”一起 两个选项之间的对应关系。然后是“逻辑论证”: Django 在 Python 代码中处理其逻辑,而不是在数据库中,数据库是 保存为一个简单的存储引擎。 RESTRICT 选项是一种验证 问题,并且在大多数情况下可能会以这种方式处理,所以有 执行它的数据库将是多余的。启用它 模型级别可以为一些不错的新自动验证铺平道路 在 ModelForms 中,所以我认为这听起来是一个不错的功能。如果这一切 已实现,我建议从 key 中删除 null 选项 字段并根据 on_delete 设置。
多年后,这件事又在群里讨论。
Django 开发人员(对 Django 本身的贡献)changing the on_delete=CASCADE default
然后创建其他票证 #21127 和 #21961。
我们到了这里。 ForeignKey and OneToOneField on_delete argument
为了提高对级联模型删除的认识, ForeignKey 和 OneToOneField 的 on_delete 参数将在 Django 2.0。
更新模型和现有迁移以显式设置参数。 由于默认是models.CASCADE,添加on_delete=models.CASCADE 所有不使用不同选项的 ForeignKey 和 OneToOneFields。 如果你不这样做,你也可以将它作为第二个位置参数传递 关心与旧版本 Django 的兼容性。
【讨论】:
感谢所有这些内容!很高兴听到有计划向前推进的替代方案,很高兴听到我并不是唯一一个认为这很愚蠢的人 ;-)。我特别喜欢明确设置 on_null 参数的想法。关于它的原始理由的任何想法,还是已经被风吹散了? 很好的这种级联行为,但如果也调用子对象的python删除方法会更好,而不是只对数据库施加SQL级联约束......幸运的是,我们有pre_delete和 post_delete 信号!所以专业提示:永远不要覆盖模型上的删除方法,而是使用信号! (太糟糕了,它与批量创建和批量更新不一样......但这是另一回事)【参考方案2】:对此in this ticket 进行了相当长的讨论。在 Django 2.0 中,on_delete
参数 will be required 将不再适用当前的默认行为。
【讨论】:
以上是关于为啥 Django 对外键进行级联删除?的主要内容,如果未能解决你的问题,请参考以下文章