РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
44 of 818 menu

ManyToManyField

Поле ManyToManyField предназначено для организации связи "многие ко многим" между двумя моделями. Оно создает промежуточную таблицу в базе данных, которая хранит связи между экземплярами моделей. Поле принимает класс модели, с которой устанавливается связь, и предоставляет API для работы с связанными объектами через менеджер отношений.

Синтаксис

from django.db import models class ModelName(models.Model): field_name = models.ManyToManyField( OtherModel, **options )

Пример

Давайте создадим модели для блога, где статья может иметь множество тегов, а один тег может принадлежать множеству статей:

from django.db import models class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) tags = models.ManyToManyField('Tag', related_name='articles') def __str__(self): return self.title class Tag(models.Model): name = models.CharField(max_length=50, unique=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.name

Пример

Добавим теги к статьям и получим все статьи для определенного тега:

from myapp.models import Article, Tag # Create tags python_tag = Tag.objects.create(name='python') django_tag = Tag.objects.create(name='django') api_tag = Tag.objects.create(name='api') # Create article and add tags article = Article.objects.create( title='Django REST Framework', content='Creating REST API with Django' ) article.tags.add(python_tag, django_tag, api_tag) # Get all articles for python tag res = python_tag.articles.all() print(res)

Результат выполнения кода:

[<Article: Django REST Framework>]

Параметры

Поле ManyToManyField принимает несколько важных параметров, влияющих на поведение связи:

  • to - обязательный параметр, указывает на модель, с которой устанавливается связь
  • related_name - имя для обратной связи от связанной модели к текущей
  • through - модель для промежуточной таблицы, позволяет хранить дополнительные данные
  • through_fields - явное указание полей в промежуточной модели
  • symmetrical - определяет симметричность связи для рекурсивных отношений

Пример

Используем параметр related_name для получения статей через тег:

from myapp.models import Tag # Get tag by name tag = Tag.objects.get(name='python') # Get all articles with this tag res = tag.articles.all() for article in res: print(article.title)

Результат выполнения кода:

"Django REST Framework" "Python Basics"

Пример

Добавим несколько тегов к статье и удалим один из них:

from myapp.models import Article, Tag # Get article and tags article = Article.objects.get(title='Django REST Framework') tag1 = Tag.objects.get(name='python') tag2 = Tag.objects.get(name='django') tag3 = Tag.objects.get(name='api') # Add multiple tags article.tags.add(tag1, tag2, tag3) # Remove one tag article.tags.remove(tag2) # Get all tags for article res = article.tags.all() for tag in res: print(tag.name)

Результат выполнения кода:

"python" "api"

Пример

Очистим все теги у статьи и проверим результат:

from myapp.models import Article # Get article article = Article.objects.get(title='Django REST Framework') # Clear all tags article.tags.clear() # Check if tags exist res = article.tags.exists() print(res)

Результат выполнения кода:

"False"

Пример

Используем промежуточную модель для хранения дополнительной информации о связи:

from django.db import models class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() tags = models.ManyToManyField( 'Tag', through='ArticleTag', related_name='articles' ) class Tag(models.Model): name = models.CharField(max_length=50, unique=True) class ArticleTag(models.Model): article = models.ForeignKey(Article, on_delete=models.CASCADE) tag = models.ForeignKey(Tag, on_delete=models.CASCADE) added_at = models.DateTimeField(auto_now_add=True) order = models.IntegerField(default=0) class Meta: ordering = ['order']

Пример

Работаем со связью через промежуточную модель:

from myapp.models import Article, Tag, ArticleTag # Create objects article = Article.objects.create( title='Advanced Django', content='Deep dive into Django' ) tag = Tag.objects.create(name='advanced') # Create relationship with extra data ArticleTag.objects.create( article=article, tag=tag, order=1 ) # Get all tags for article with extra data res = ArticleTag.objects.filter(article=article) for rel in res: print(f"{rel.tag.name} - order: {rel.order}")

Результат выполнения кода:

"advanced - order: 1"

Смотрите также

  • поле ForeignKey,
    которое создает связь "один ко многим"
  • поле OneToOneField,
    которое создает связь "один к одному"
  • метод add,
    который добавляет объекты в отношение
  • метод remove,
    который удаляет объекты из отношения
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить