Ссылка на связанные объекты
-
class RelatedManager -
«Менеджер связанных объектов» — это менеджер, используемый в контексте связи «один ко многим» или «многие ко многим». Это происходит в двух случаях:
-
«Другая сторона» связи
ForeignKey. То есть:from django.db import models class Blog(models.Model): # ... pass class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)В приведённом примере методы ниже будут доступны в менеджере
blog.entry_set. -
Обе стороны связи
ManyToManyFieldclass Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)В этом примере методы ниже будут доступны как в
topping.pizza_set, так и вpizza.toppings.
-
add(*objs, bulk=True, through_defaults=None)
-
aadd(*objs, bulk=True, through_defaults=None) -
Асинхронная версия:
aaddДобавляет указанные объекты модели в набор связанных объектов.
Пример:
>>> 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()для уже существующей связи не продублирует связь, но всё равно вызовет сигналы.Для связей «многие ко многим»
add()принимает в качестве аргумента*objsэкземпляры моделей или значения полей, обычно первичные ключи.Используйте аргумент
through_defaultsдля указания значений для нового(ых) экземпляра(ов) промежуточной модели, если это необходимо. Вы можете использовать вызываемые объекты в словареthrough_defaults, и они будут оценены один раз перед созданием любого экземпляра промежуточной модели.
-
create(through_defaults=None, **kwargs)
-
acreate(through_defaults=None, **kwargs) -
Асинхронная версия:
acreateСоздаёт новый объект, сохраняет его и добавляет в набор связанных объектов. Возвращает только что созданный объект:
>>> 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.Используйте аргумент
through_defaultsдля указания значений для нового экземпляра промежуточной модели, если это необходимо. Вы можете использовать вызываемые объекты в словареthrough_defaults.
-
remove(*objs, bulk=True)
-
aremove(*objs, bulk=True) -
Асинхронная версия:
aremoveУдаляет указанные объекты модели из набора связанных объектов:
>>> 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, если вы хотите выполнить пользовательский код при удалении связи.Для связей «многие ко многим»
remove()принимает в качестве аргумента*objsэкземпляры моделей или значения полей, обычно первичные ключи.Для объектов
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)
-
aclear(bulk=True) -
Асинхронная версия:
aclearУдаляет все объекты из набора связанных объектов:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
Обратите внимание, что это не удаляет связанные объекты — это просто отсоединяет их.
Так же как и
remove(),clear()доступен только дляForeignKey, гдеnull=True, и он также принимает ключевой аргументbulk.Для связей «многие ко многим» ключевой аргумент
bulkне существует.
-
set(objs, bulk=True, clear=False, through_defaults=None)
-
aset(objs, bulk=True, clear=False, through_defaults=None) -
Асинхронная версия:
asetЗаменяет набор связанных объектов:
>>> 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().Для связей «многие ко многим»
set()принимает в качестве аргументаobjsсписок экземпляров моделей или значений полей, обычно первичные ключи.Используйте аргумент
through_defaultsдля указания значений для нового(ых) экземпляра(ов) промежуточной модели, если это необходимо. Вы можете использовать вызываемые объекты в словареthrough_defaults, и они будут оценены один раз перед созданием любого экземпляра промежуточной модели.
-
Примечание
Обратите внимание, что
add(),aadd(),create(),acreate(),remove(),aremove(),clear(),aclear(),set()иaset()немедленно применяют изменения в базе данных для всех типов связанных полей. Другими словами, нет необходимости вызыватьsave()/asave()с любой стороны отношения.Если вы используете
prefetch_related(), методыadd(),aadd(),remove(),aremove(),clear(),aclear(),set()иaset()очищают кэш предварительной выборки.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/ref/models/relations/