Django是否应该实现DB
我有一个Django 1.3应用程序,我正在使用South 0.7.3进行数据库迁移。 我有一个问题, on_delete=models.SET_NULL
规则似乎并没有在父实体被删除时触发,因此给我一个来自底层DB(即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
然后我阅读了Django文档中的on_delete规则,这些规则说明了(我的强调):
当被ForeignKey引用的对象被删除时,Django默认模拟 SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象。 这种行为可以通过指定on_delete参数来覆盖。
“模拟”部分向我建议,Django试图自己实现on_delete行为,并且不依赖底层DB来自动执行这个事务作为事务的一部分,从而使得南方的bug无关紧要。
我在Django源代码中通过db/models/deletion.py
来戳,并且基于SET()
/ SET_NULL()
和collect()
它看起来像Django本身应该这样做,但是,如果我尝试为了从Django管理员中删除一个AccessPeriod,我在Payments表上为它仍然引用的ID取得约束违规,现在它被删除了,也就是说它看起来好像Django在Payment.period
关系中调用SET_NULL()
作为对accessPeriod.delete()
的调用。
我在这里做错了什么,或者误解Django应该做什么? 试图避免手动黑客DB来插入ON DELETE规则,这感觉非常脆弱和可怕。
在我的具体情况中,我将这个bug追溯到我的models.py代码中的ModelAdmin内联的声明,导致我的模型类被错误地实例化,破坏的on_delete
行为是最明显的副作用。 从我的提交信息:
修复了级联删除在Django DB中没有正确完成的问题。
事实证明,不要在models.py的全局范围内声明ModelAdmins,否则不同模型之间的所有关系都会在加载所有模型之前计算出来,并且大部分模型都会被忽略。 在Django文档中,真的没有那么强调这一点。
因此,在我最初的(破碎的)代码中,我会在每个模型的ModelAdmin后立即声明一个la:
class AccessPeriod( models.Model ):
....
class AccessPeriodAdmin( models.ModelAdmin ):
....
# This causes the metaclass setup for AccessPeriod to happen right now,
# and since related models for AccessPeriod are not all declared yet,
# relationship handling behaviour becomes broken for AccessPeriod
admin.site.register( AccessPeriod, AccessPeriodAdmin )
class Payment( models.Model ):
....
class PaymentAdmin( models.ModelAdmin ):
....
# Same effect on the Payment model here
admin.site.register( Payment, PaymentAdmin )
解决方案是将所有ModelAdmin声明从myapp/models.py
移出myapp/admin.py
以便在处理所有模型声明之后,为每个类设置所有的metaclass设置,然后所有关系开始正常运行再次。
上一篇: Is Django supposed to implement DB on
下一篇: Create a custom view using a nib and use it in a window