使用以下相关模型(一个博客条目可以有多个修订版):
class BlogEntryRevision(models.Model):
revisionNumber = models.IntegerField()
title = models.CharField(max_length = 120)
text = models.TextField()
[...]
class BlogEntry(models.Model):
revisions = models.ManyToManyField(BlogEntryRevision)
[...]
当相应的BlogEntryRevision
被删除时,如何告诉Django删除所有相关的BlogEntry
s?如果删除了“其他”端的对象,则默认似乎是将对象保持为多对多关系。任何方式这样做 - 最好不要覆盖BlogEntry.delete
?
我认为你误解了ManyToMany关系的本质。你谈到被删除的“相应的BlogEntry”。但是,ManyToMany的重点在于每个BlogEntryRevision都有多个与之相关的BlogEntries。 (当然,每个BlogEntry都有多个BlogEntryRevisions,但你已经知道了。)
从您使用的名称,以及您想要删除级联功能的事实来看,我认为使用BlogEntryRevision到BlogEntry的标准ForeignKey会更好。只要您没有在该ForeignKey上设置null=True
,删除就会被删除 - 当删除BlogEntry时,所有修订也将被删除。
我今天有这个确切的用例:
为此,我正在使用多对多关系。
我的用例是:如果我删除特定作者的最后一个条目,那么也应该删除该作者。
使用pre_delete
signal可以实现解决方案:
@receiver(pre_delete, sender=Entry)
def pre_delete_story(sender, instance, **kwargs):
for author in instance.authors.all():
if author.entries.count() == 1 and instance in author.entries.all():
# instance is the only Entry authored by this Author, so delete it
author.delete()
你可以使用custom model manager,但文档似乎表明它does do something like this already和我不记得这究竟是什么意思:
删除方法很方便地命名为delete()。此方法立即删除对象并且没有返回值。例:
e.delete()
您也可以批量删除对象。每个QuerySet都有一个delete()方法,该方法删除该QuerySet的所有成员。
例如,这将删除pub_date年份为2005的所有Entry对象:
Entry.objects.filter(pub_date__year=2005).delete()
请记住,只要有可能,这将完全在SQL中执行,因此在此过程中不一定会调用各个对象实例的delete()方法。如果您在模型类上提供了自定义delete()方法并希望确保调用它,则需要“手动”删除该模型的实例(例如,通过迭代QuerySet并调用delete()on每个对象单独)而不是使用QuerySet的批量delete()方法。
当Django删除一个对象时,它会模拟SQL约束ON DELETE CASCADE的行为 - 换句话说,任何具有指向要删除的对象的外键的对象都将随之删除。例如:
b = Blog.objects.get(pk=1) # This will delete the Blog and all of its Entry objects. b.delete()
只需使用clear()
方法删除相关对象,因为Django使用直通模型来指定clear方法删除所有相关BlogEntryRevision
的关系
be = BlogEntry.objects.get(id=1)
be.blogentryrevision_set.clear()