Python Django-什么是cascade的反向等价物?
我正在写一个小的音乐数据库。学习SQL在我的过去有相当长的一段时间,我一直想尝试一下django。但有一件事我无法理解 现在,我的模型只有两个类,Python Django-什么是cascade的反向等价物?,python,django,Python,Django,我正在写一个小的音乐数据库。学习SQL在我的过去有相当长的一段时间,我一直想尝试一下django。但有一件事我无法理解 现在,我的模型只有两个类,Album和Song。 歌曲有一个外键指向它所属的唱片集。现在,如果我删除那张专辑,由于层叠效应,所有属于它的歌曲都将被删除 相册在我的数据库中是虚拟的,文件系统上实际上只显示歌曲,并且相册是根据歌曲标签构建的,因此,如果没有更多指向它的歌曲,我只能知道相册不再存在(因为它们不再存在于文件系统中) 或者简言之,如何实现反向级联,也就是说,如果没有更多的
Album
和Song
。
歌曲
有一个外键指向它所属的唱片集。现在,如果我删除那张专辑
,由于层叠效应,所有属于它的歌曲都将被删除
相册在我的数据库中是虚拟的,文件系统上实际上只显示歌曲,并且相册是根据歌曲标签构建的,因此,如果没有更多指向它的歌曲,我只能知道相册不再存在(因为它们不再存在于文件系统中)
或者简言之,如何实现反向级联,也就是说,如果没有更多的歌曲指向唱片集,那么唱片集也应该被删除?当一首歌曲被删除且没有更多歌曲时,您可以使用该信号删除唱片集
from yourapp.models import Album, Song
from django.db.models.signals import pre_delete
def delete_parent(sender, **kwargs):
# Here you check if there are remaining songs.
....
pre_delete.connect(delete_parent, sender=Song)
我也遇到过类似的问题,最后我在相册中添加了一个计数器。如果计数为0且操作为delete(),则相册对象为delete()d
其他解决方案包括在歌曲模型中重载delete()方法,或使用post delete删除相册 Django 1.3将提供定制级联行为的能力[1],但据我所知,仍然没有办法自动实现您所描述的功能
最好的方法可能是为您的Song
类编写post\u delete
信号处理程序[2],该处理程序检查相关的Album
是否有剩余的Song
并在适当时将其删除。我相信ForeignKey
值应该仍然存在于实例
参数中,尽管歌曲
已从数据库中删除。(如果没有,请尝试使用pre_delete
)
或者,您可以覆盖delete
方法[3],但根据您删除对象的方式,并不总是调用该方法
[1]
[2]
[3] 有一个非常微妙的实现点,我认为我应该补充到这个讨论中
假设我们有两个模型,其中一个通过外键引用另一个,如中所示:
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
这段代码将以任何方式工作。我希望它能帮助一些人