Django级联删除反向外键

时间:2012-09-29 18:30:05

标签: python mysql django

Django展示了如何在文档中使用外键设置或覆盖级联删除。

model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL)

但是如果我们想要这种效果呢?如果我们想删除fk模型导致删除此模型该怎么办?

由于

2 个答案:

答案 0 :(得分:11)

有一个非常微妙的实施点,我认为我应该加入这个讨论。

假设我们有两个模型,其中一个模型通过外键引用另一个模型,如:

class A(models.Model):
    x = models.IntegerField()

class B(models.Model):
    a = models.ForeignKey(A, null=True, blank=True)

现在,如果删除A的条目,级联行为也会导致B中的引用被删除。

到目前为止,这么好。现在我们想要扭转这种行为。人们提到的显而易见的方法是使用删除期间发出的信号,所以我们去:

def delete_reverse(sender, **kwargs):
    if kwargs['instance'].a:
        kwargs['instance'].a.delete()

post_delete.connect(delete_reverse, sender=B)

这似乎是完美的。它甚至有效!如果我们删除B条目,则相应的A也将被删除。

问题是这有一个循环行为导致异常:如果我们删除A的项目,由于默认的级联行为(我们想要保留),B的相应项目也将被删除,将导致调用delete_reverse,它会尝试删除已删除的项目!

诀窍是,你需要EXCEPTION HANDLING才能正确实现反向级联:

def delete_reverse(sender, **kwargs):
    try:
        if kwargs['instance'].a:
            kwargs['instance'].a.delete()
    except:
        pass

此代码将以任何方式工作。我希望它可以帮助一些人。

答案 1 :(得分:1)

我认为您所看到的功能不是ORM或数据库概念。您只想在删除某些内容时执行回调。

所以使用post_delete signal并在那里添加回调处理程序

from django.db.models.signals import post_delete
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(post_delete, sender=MyModel)
def my_post_delete_callback(sender, **kwargs):
    #Sender is the model which when deleted should trigger this action
    #Do stuff like delete other things you want to delete
    #The object just deleted can be accessed as kwargs[instance]