Django-каскадное удаление в ManyToManyRelation

используя следующие связанные модели (одна запись в блоге может иметь несколько версий):

class BlogEntryRevision(models.Model):
    revisionNumber = models.IntegerField()
    title = models.CharField(max_length = 120)
    text = models.TextField()
    [...]

class BlogEntry(models.Model):
    revisions = models.ManyToManyField(BlogEntryRevision)
    [...]

как я могу сказать Django удалить все связанные BlogEntryRevisions, когда соответствующее BlogEntry удаляется? Кажется, что по умолчанию объекты находятся в отношении "многие ко многим", если объект" другой " стороны удален. Любой способ сделать это - желательно без переопределения BlogEntry.delete?

4 ответов


Я думаю, что вы неправильно понимаете природу отношений ManyToMany. Вы говорите об удалении" соответствующего блога". Но весь смысл ManyToMany в том, что каждый BlogEntryRevision имеет несколько BlogEntries, связанные с ним. (И, конечно, каждый BlogEntry имеет несколько BlogEntryRevisions,но вы это уже знаете.)

из имен, которые вы использовали, и тот факт, что вы хотите эту функциональность каскада удаления, я думаю, вам было бы лучше выкл со стандартным ForeignKey из BlogEntryRevision в BlogEntry. Пока вы не установите null=True на этом ForeignKey удаление будет cascase-когда BlogEntry будет удален, все ревизии тоже будут.


у меня был точно такой же случай сегодня:

  • автор модели: может иметь несколько записей
  • модель записи: может иметь несколько авторов

для этого я использую 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()

можно использовать пользовательский менеджер моделей, но документация, похоже, указывает, что это делает что-то подобное уже и я не могу точно вспомнить, что это значит:

метод удаления, удобно, именем delete(). Этот метод немедленно удаляет объект и нет возвращаемого значения. Пример:

e.delete()

вы также можете удалить объекты навалом. Каждый QuerySet имеет удаление() метод, который удаляет все члены что объект QuerySet.

например, это удаляет все записи объекты с pub_date 2005 года:

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

имейте в виду, что это будет, когда возможно, выполняться чисто в SQL, и поэтому методы delete () отдельные экземпляры объектов не будут обязательно во время процесс. Если вы предоставили пользовательский метод delete () для класса модели и хотите убедиться, что это называется, вы нужно будет" вручную " удалить примеры этой модели (например, итерация по QuerySet и вызов Удалить() для каждого объекта по отдельности) вместо использования массового удаления() метод QuerySet.

когда Django удаляет объект, он эмулирует поведение SQL ограничение на DELETE CASCADE -- in другими словами, любые предметы, которые внешние ключи, указывающие на объект быть удаленным будет удален вместе с он. например:

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()