gle*_*enc 7 django orm constraints django-south
我有一个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 )
Run Code Online (Sandbox Code Playgroud)
经过一番挖掘,我发现南方实际上没有将ON DELETE
子句插入它为迁移生成的SQL中,因此DB绝对不会对破坏的关系本身进行无效处理:
http://south.aeracode.org/ticket/763
然后我读了关于on_delete规则的Django文档,其中说明了(我的重点):
删除ForeignKey引用的对象时,Django默认模拟 SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象.可以通过指定on_delete参数来覆盖此行为.
"模拟"部分向我建议Django尝试实现on_delete行为本身,并且不依赖于底层数据库自动执行此操作作为事务的一部分,从而使South bug无关紧要.
我db/models/deletion.py
在Django源代码中找到了一个基于SET()
/ 的实现,SET_NULL()
并且collect()
看起来Django本身应该这样做,但是,如果我尝试从Django管理员中删除一个AccessPeriod,我会在Payments上出现约束违规行为它仍然引用的ID表现在已被删除,即看起来Django似乎并未调用SET_NULL()
该Payment.period
关系作为调用的一部分accessPeriod.delete()
.
我在这里做错了什么,或者误解了Django应该做什么?只是试图避免手动黑客攻击数据库自己插入ON DELETE规则,这感觉非常脆弱和可怕.
在我的具体情况下,我将此错误追溯到 models.py 代码中内联的 ModelAdmin 声明,导致我的模型类被错误地实例化,而破坏的on_delete
行为是最明显的副作用。来自我的提交消息:
修复了 Django DB 中级联删除未正确完成的问题。
事实证明,不要在 models.py 的全局范围内声明 ModelAdmins 非常重要,否则在加载所有模型之前就会计算不同模型之间的所有关系,并且许多模型会被遗漏。Django 文档中确实没有那么强调这一点。
因此,在我原来的(损坏的)代码中,我将在每个模型之后立即声明 ModelAdmin,如下所示:
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 )
Run Code Online (Sandbox Code Playgroud)
解决方案是将所有 ModelAdmin 声明移出myapp/models.py
和移入myapp/admin.py
,以便在处理所有模型声明之后发生每个类的所有元类设置,然后所有关系再次开始正常运行。
归档时间: |
|
查看次数: |
1087 次 |
最近记录: |