Django反向反向键上的级联删除 [英] Django cascade delete on reverse foreign keys

查看:125
本文介绍了Django反向反向键上的级联删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Django shows how to set or override cascade deletes with foreign keys in their documents.

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

但是,如果我们希望这种效果反过来又会怎样呢?如果我们希望删除fk模型导致删除该模型怎么办?

But what if we wanted this effect the other way around? What if we want the deletion of the fk model to result in the deletion of this model?

谢谢

推荐答案

有一个非常微妙的实现点,我认为我应该在此讨论中加入.

There is a very delicate implementation point, that I thought I should add to this discussion.

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

Let's say we have two models, one of which references the other one by a foreign key, as in:

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

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

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

Now if we delete an entry of A, the cascading behavior will cause the reference in B to be deleted as well.

到目前为止,太好了.现在我们要扭转这种行为.人们提到的最明显的方法是使用删除期间发出的信号,所以我们去:

So far, so good. Now we want to reverse this behavior. The obvious way as people have mentioned is to use the signals emitted during delete, so we go:

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

post_delete.connect(delete_reverse, sender=B)

这似乎是完美的.它甚至可以工作!如果我们删除B条目,则相应的A也将被删除.

This seems to be perfect. It even works! If we delete a B entry, the corresponding A will also be deleted.

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

The PROBLEM is that this has a circular behavior which causes an exception: If we delete an item of A, because of the default cascading behavior (which we want to keep), the corresponding item of B will also be deleted, which will cause the delete_reverse to be called, which tries to delete an already deleted item!

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

The trick is, you need EXCEPTION HANDLING for proper implementation of reverse cascading:

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

此代码将以任何一种方式工作.我希望它能对某些人有所帮助.

This code will work either way. I hope it helps some folks.

这篇关于Django反向反向键上的级联删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆