Как в Django ORM определить связь many-to-many между моделями

Ответ

Связь «многие-ко-многим» в Django ORM создается с помощью поля models.ManyToManyField. Django автоматически создает промежуточную (join) таблицу для управления этими отношениями.

Это позволяет, например, связать одного автора с несколькими книгами и одну книгу с несколькими авторами.

Базовый пример

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=100)
    # Определение связи many-to-many
    authors = models.ManyToManyField(Author, related_name='books')

    def __str__(self):
        return self.title

Основные операции

Для управления связями используются специальные методы менеджера:

  • add(): добавляет объекты в связь.
  • remove(): удаляет объекты из связи.
  • set(): полностью заменяет набор связанных объектов.
  • clear(): удаляет все объекты из связи.
# Получаем объекты
author1 = Author.objects.get(name='Лев Толстой')
book = Book.objects.get(title='Война и мир')

# Добавляем автора к книге
book.authors.add(author1)

# Фильтрация по связанной модели
books_by_tolstoy = Book.objects.filter(authors__name='Лев Толстой')

Пользовательская промежуточная модель (through)

Если вам нужно хранить дополнительные данные о самой связи (например, дату вступления участника в группу), используется опция through.

class Membership(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    # Дополнительное поле
    role = models.CharField(max_length=50, default='author')

# Модель Book теперь ссылается на Membership
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author, through='Membership')