Ссылка на связанные объекты
-
class RelatedManager -
«Менеджер связанных объектов» — это менеджер, используемый в контексте связи «один ко многим» или «многие ко многим». Это происходит в двух случаях:
-
«Другая сторона» связи
ForeignKey. То есть:from django.db import models class Reporter(models.Model): # ... pass class Article(models.Model): reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)В приведённом примере методы ниже будут доступны для менеджера
reporter.article_set. -
Обе стороны связи
ManyToManyField:class Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)В этом примере методы ниже будут доступны как для
topping.pizza_set, так и дляpizza.toppings.
-
add(*objs, bulk=True) -
Добавляет указанные объекты модели в набор связанных объектов.
Пример:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.add(e) # Associates Entry e with Blog b.
В приведённом примере, в случае связи
ForeignKey, используетсяQuerySet.update()для выполнения обновления. Это требует, чтобы объекты уже были сохранены.Можно использовать аргумент
bulk=Falseдля того, чтобы менеджер связанных объектов выполнил обновление, вызвавe.save().Использование
add()с связью «многие ко многим», однако, не вызовет никаких методовsave(), (аргументbulkне существует), а вместо этого создаст связи с помощьюQuerySet.bulk_create(). Если требуется выполнить некоторую пользовательскую логику при создании связи, прослушайте сигналm2m_changed, который вызовет действияpre_addиpost_add.Использование
add()для уже существующей связи не создаст дублирования, но всё равно вызовет сигналы.
-
create(**kwargs) -
Создаёт новый объект, сохраняет его и добавляет в набор связанных объектов. Возвращает только что созданный объект:
>>> b = Blog.objects.get(id=1) >>> e = b.entry_set.create( ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) # No need to call e.save() at this point -- it's already been saved.
Это эквивалентно (но намного проще):
>>> b = Blog.objects.get(id=1) >>> e = Entry( ... blog=b, ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) >>> e.save(force_insert=True)
Обратите внимание, что не нужно указывать ключевой аргумент модели, определяющей связь. В приведённом примере мы не передаём параметр
blogвcreate(). Django определяет, что полеEntryнового объектаblogдолжно быть установлено вb.
-
remove(*objs, bulk=True) -
Удаляет указанные объекты модели из набора связанных объектов:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
Аналогично
add(), в примере выше вызываетсяe.save(), чтобы выполнить обновление. Однако, использованиеremove()с связью «многие ко многим» удалит связи с помощьюQuerySet.delete(), что означает, что не вызываются никакие методы моделиsave(); прослушивайте сигналm2m_changed, если хотите выполнить пользовательский код при удалении связи.Для объектов
ForeignKey, этот метод существует только еслиnull=True. Если связанное поле не может быть установлено вNone(NULL), то объект нельзя удалить из связи без добавления в другую. В приведённом примере удалениеeизb.entry_set()эквивалентно выполнениюe.blog = None, и поскольку уblogForeignKeyнетnull=True, это недопустимо.Для объектов
ForeignKey, этот метод принимает аргументbulkдля управления способом выполнения операции. ЕслиTrue(значение по умолчанию), используетсяQuerySet.update(). Еслиbulk=False, вместо этого вызывается методsave()каждого отдельного экземпляра модели. Это вызывает сигналыpre_saveиpost_save, что отражается на производительности.Для связей «многие ко многим» аргумент
bulkне существует.
-
clear(bulk=True) -
Удаляет все объекты из набора связанных объектов:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
Обратите внимание, что это не удаляет связанные объекты — это просто отсоединяет их.
Как и
remove(),clear()доступно только дляForeignKey, гдеnull=True, и оно также принимает аргументbulk.Для связей «многие ко многим» аргумент
bulkне существует.
-
set(objs, bulk=True, clear=False) -
Заменяет набор связанных объектов:
>>> new_list = [obj1, obj2, obj3] >>> e.related_set.set(new_list)
Этот метод принимает аргумент
clearдля управления способом выполнения операции. ЕслиFalse(значение по умолчанию), элементы, отсутствующие в новом наборе, удаляются с помощьюremove(), и только новые добавляются. Еслиclear=True, вместо этого вызывается методclear()и весь набор добавляется сразу.Для объектов
ForeignKey, аргументbulkпередаётся вadd()иremove().Для связей «многие ко многим» аргумент
bulkне существует.Обратите внимание, что, поскольку
set()— это сложная операция, она может быть подвержена проблемам гонок. Например, новые объекты могут быть добавлены в базу данных между вызовомclear()и вызовомadd().
Примечание
Обратите внимание, что
add(),create(),remove(),clear(), иset()немедленно применяют изменения в базе данных для всех типов связанных полей. Другими словами, нет необходимости вызыватьsave()ни с одной стороны связи.Также, если вы используете промежуточную модель для связи «многие ко многим», методы
add(),create(),remove(), иset()отключены.Если вы используете
prefetch_related(), методыadd(),remove(),clear(), иset()очищают кэш предварительной выборки. -
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.1/ref/models/relations/