Django是否应该在_delete规则本身上实现DB?

Django是否应该在_delete规则本身上实现DB?,django,orm,constraints,django-south,Django,Orm,Constraints,Django South,我有一个Django 1.3应用程序,我正在使用South 0.7.3进行DB迁移。我有一个问题,当父实体被删除时,一个on_delete=models.SET_NULL规则似乎没有被触发,因此给了我一个来自底层数据库(即Postgres 8.4)的约束冲突 实体定义的相关部分包括: class AccessPeriod: .... class Payment: period = models.ForeignKey( AccessPeriod, related

我有一个Django 1.3应用程序,我正在使用South 0.7.3进行DB迁移。我有一个问题,当父实体被删除时,一个
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实际上并没有在它为迁移生成的SQL中插入
ON DELETE
子句,因此DB肯定不会对中断的关系本身进行消空:

然后,我阅读了Django文档中关于on_delete规则的内容,其中指出(我的重点):

删除ForeignKey引用的对象时,Django 默认值模拟删除级联上SQL约束的行为 并删除包含ForeignKey的对象。这种行为 可以通过指定on_delete参数来覆盖

“模拟”部分向我建议Django尝试实现on_delete行为本身,而不依赖底层数据库作为事务的一部分自动执行,因此使South bug变得无关紧要

我在Django源代码中浏览了
db/models/deletation.py
,基于
SET()
/
SET\u NULL()
collect()
的实现,Django似乎应该自己做这件事,但是,如果我试图从Django管理员中删除一个访问周期,我在Payments表中得到了它仍然引用的ID的约束冲突,该ID现在已被删除,即Django似乎没有调用
Payment.period
关系上的
SET\u NULL()
,作为调用
accessPeriod.delete()
的一部分


我是做错了什么,还是误解了Django应该做什么?我只是想避免手动入侵数据库,自己插入ON DELETE规则,这感觉非常脆弱和可怕。

在我的具体案例中,我将此错误追溯到models.py代码中ModelAdmin inline的声明,导致我的模型类被错误实例化,当您删除行为时,最明显的副作用就是出现了中断的
。从我的提交消息:

修复了Django中级联删除操作不正确的问题 DB

事实证明,不要在models.py的全局范围内声明ModelAdmins非常重要,否则所有关系 在计算所有模型之前,先计算不同模型之间的差异 他们中的很多人被遗漏了。真的不是那么强调吗 关于这一点,请参阅Django文档

因此,在我的原始(不完整的)代码中,我会在每个模型之后立即声明模型管理员,即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
,这样每个类的所有元类设置都会在处理完所有模型声明之后进行,然后,所有的关系又开始正常运行。

如果您从postgres失败时获得堆栈跟踪,那么这可能会提供错误位置的线索。这可能是你忽略了的东西。