【发布时间】:2011-07-11 13:04:15
【问题描述】:
我有一个 Django 1.3 应用程序,我使用 South 0.7.3 进行数据库迁移。我有一个问题,当父实体被删除时,on_delete=models.SET_NULL 规则似乎没有被触发,从而给了我来自底层数据库(即 Postgres 8.4)的约束违规。
实体定义的相关部分是:
class AccessPeriod:
....
class Payment:
period = models.ForeignKey(
AccessPeriod, related_name = "payments", db_index = True,
null = True, on_delete = models.SET_NULL )
经过一番挖掘,我发现 South 实际上并没有将 ON DELETE 子句插入到它为迁移生成的 SQL 中,因此数据库肯定不会对损坏的关系本身进行无效化:
http://south.aeracode.org/ticket/763
然后我阅读了关于 on_delete 规则的 Django 文档,其中指出(我的重点):
当一个 ForeignKey 引用的对象被删除时,Django 通过 默认 模拟 SQL 约束 ON DELETE CASCADE 的行为 并删除包含 ForeignKey 的对象。这种行为 可以通过指定 on_delete 参数来覆盖。
“模拟”部分向我建议,Django 尝试自己实现 on_delete 行为,并且不依赖底层数据库作为事务的一部分自动执行此操作,从而使 South 错误无关紧要。
我对 Django 源代码中的 db/models/deletion.py 进行了探讨,基于 SET() / SET_NULL() 和 collect() 的实现,似乎 Django 应该自己执行此操作,但是,如果我尝试从 Django 管理员中删除一个 AccessPeriod,我在 Payments 表上遇到了它仍然引用的 ID 的约束违规,该 ID 现在已被删除,即 Django 似乎没有在 Payment.period 关系上调用 SET_NULL() 作为致电accessPeriod.delete()。
我在这里做错了什么,或者误解了 Django 应该做什么?只是想避免自己手动破解数据库来插入 ON DELETE 规则,这感觉非常脆弱和可怕。
【问题讨论】:
-
如果您从 postgres 失败时获得堆栈跟踪,也许这会知道哪里出错了。这可能是你忽略的东西。
标签: django orm constraints django-south