Метод set
Метод set применяется к менеджеру связанных объектов
и заменяет текущий набор связанных объектов на указанный.
Он доступен для отношений ManyToManyField и
ForeignKey (через обратную связь). В качестве
аргумента метод принимает итерабельный объект с идентификаторами
или экземплярами моделей. Для отношения многие-ко-многим
метод выполняет атомарную замену всего набора, автоматически
удаляя старые связи и добавляя новые.
Синтаксис
instance.related_manager.set(objs)
Где instance - экземпляр модели, имеющий связанное
поле, а related_manager - менеджер связанных
объектов. Параметр objs - список идентификаторов
или экземпляров моделей, которые должны стать новым набором
связанных объектов.
Пример . Для ManyToManyField
Пусть у нас есть модели Article и Category
со связью многие-ко-многим. Заменим все категории для
конкретной статьи на новые:
from myapp.models import Article, Category
article = Article.objects.get(pk=1)
new_categories = Category.objects.filter(name__in=['python', 'django'])
article.categories.set(new_categories)
Можно также передать список идентификаторов:
from myapp.models import Article
article = Article.objects.get(pk=1)
article.categories.set([1, 2, 3])
Пример . Для ForeignKey
Для внешнего ключа метод set доступен через
обратную связь. Заменим все статьи для конкретного автора:
from myapp.models import Author, Article
author = Author.objects.get(pk=1)
new_articles = Article.objects.filter(status='published')
author.article_set.set(new_articles)
Пример . С добавлением и удалением
Метод set полностью заменяет набор, удаляя
все связи, которые не входят в новый список. Поэтому
его использование эквивалентно последовательному
вызову clear и add:
from myapp.models import Article, Category
article = Article.objects.get(pk=1)
category_ids = [4, 5, 6]
# Полная замена набора
article.categories.set(category_ids)
При передаче пустого списка метод очищает все связи:
from myapp.models import Article
article = Article.objects.get(pk=1)
article.categories.set([])
Пример . С использованием bulk
Метод set автоматически использует bulk-операции
для оптимизации производительности. Это делает его
эффективным при работе с большими наборами данных:
from myapp.models import Article, Category
article = Article.objects.get(pk=1)
categories = Category.objects.filter(is_active=True)
# Оптимизированная замена набора
article.categories.set(categories)