Django演示了如何设置或取消在文档中使用外键级联删除。Django级联删除反向外键
model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL)
但是如果我们想要另一种方式来解决这个问题呢?如果我们想要删除fk模型导致删除此模型会怎么样?
感谢
Django演示了如何设置或取消在文档中使用外键级联删除。Django级联删除反向外键
model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL)
但是如果我们想要另一种方式来解决这个问题呢?如果我们想要删除fk模型导致删除此模型会怎么样?
感谢
我不认为你正在寻找的特征是一个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]
有一个非常微妙的实现角度,我认为我应该加入讨论。
比方说,我们有两个型号,其中一个引用外键的另一种,如:
class A(models.Model):
x = models.IntegerField()
class B(models.Model):
a = models.ForeignKey(A, null=True, blank=True)
现在,如果我们删除一个的条目中,级联行为将导致参考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
此代码将工作无论哪种方式。我希望它能帮助一些人。
顺便说一下,这可能不会导致无限递归,是不是? – minmaxavg
这种策略是不可靠的,因为'delete()'方法发出'on_delete'信号,并且'delete()'方法[不保证被调用](https://docs.djangoproject.com/en/dev/topics/db/queries /#deletion-objects)“,只要有可能,这将纯粹在SQL中执行,因此单个对象实例的delete()方法在进程中不一定会被调用。如果你在模型类上提供了一个自定义的delete()方法......“ – claytond