27

使用以下相关模型(一个博​​客条目可以有多个修订版):

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?如果“另一方”的对象被删除,默认值似乎是使对象保持多对多关系。有什么方法可以做到这一点 - 最好不要覆盖BlogEntry.delete

4

4 回答 4

23

我认为您误解了多对多关系的性质。您谈到“相应的 BlogEntry”被删除。但是ManyToMany 的全部意义在于每个BlogEntryRevision 都有多个与之相关的BlogEntries。(当然,每个 BlogEntry 都有多个 BlogEntryRevisions,但您已经知道了。)

从您使用的名称,以及您想要这种删除级联功能的事实来看,我认为您最好使用从 BlogEntryRevision 到 BlogEntry 的标准 ForeignKey。只要您不设置null=True该 ForeignKey,删除就会级联 - 当 BlogEntry 被删除时,所有 Revisions 也会被删除。

从 Django 2.0 开始

初始化程序现在ForeignKey要求您指定on_delete 参数:

from django.db import models
from .models import MyRelatedModel


class model(models.Model):
    related_model = models.ForeignKey(MyRelatedModel, on_delete=models.CASCADE)
于 2010-10-14T20:49:21.040 回答
21

我今天有这个确切的用例:

  • 模型作者:可以有多个条目
  • 模型条目:可以有多个作者

为此,我使用了 ManyToManyRelationship。

我的用例是:如果我删除了某个作者的最后一个条目,那么这个作者也应该被删除。

解决方案可以使用pre_delete信号来实现:

@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()
于 2014-10-24T10:29:08.697 回答
4

只需使用该clear()方法删除相关对象,因为 Django 使用直通模型来指定关系 clear 方法删除所有相关BlogEntryRevision

be = BlogEntry.objects.get(id=1)
be.blogentryrevision_set.clear()
于 2018-03-12T14:27:27.320 回答
2

您可以使用自定义模型管理器,但文档似乎表明它已经做了类似的事情,我不记得这到底意味着什么:

方便地,删除方法被命名为 delete()。此方法立即删除对象并且没有返回值。例子:

e.delete()

您还可以批量删除对象。每个 QuerySet 都有一个 delete() 方法,用于删除该 QuerySet 的所有成员。

例如,这将删除所有 pub_date 年份为 2005 年的 Entry 对象:

Entry.objects.filter(pub_date__year=2005).delete()

请记住,只要有可能,这将纯粹在 SQL 中执行,因此在此过程中不一定会调用单个对象实例的 delete() 方法。如果您在模型类上提供了自定义 delete() 方法并希望确保调用它,则需要“手动”删除该模型的实例(例如,通过迭代 QuerySet 并在每个对象单独)而不是使用 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()
于 2010-10-14T20:24:54.437 回答