反向外键上的Django cascade delete

2024-06-02 06:42:37 发布

您现在位置:Python中文网/ 问答频道 /正文

Django演示如何设置或重写文档中的外键级联删除。

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

但是如果我们想要相反的效果呢?如果我们希望删除fk模型会导致删除此模型,该怎么办?

谢谢


Tags: django文档模型truemodelonmodelsdelete
2条回答

有一个非常微妙的实现点,我想我应该加入到这个讨论中。

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

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,它将尝试删除已经删除的项!

诀窍在于,您需要异常处理才能正确实现反向级联:

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

这段代码不管用哪种方式都可以。我希望它能帮助一些人。

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

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

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]

相关问题 更多 >