Справочник по связанным объектам
-
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. -
Обе стороны отношения
ManyToManyField:class Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)В этом примере методы ниже будут доступны как в
topping.pizza_set, так и вpizza.toppings.
-
add(*objs, bulk=True, through_defaults=None) -
Добавляет указанные объекты модели в набор связанных объектов.
Пример:
>>> 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) -
Создаёт новый объект, сохраняет его и помещает в набор связанных объектов. Возвращает созданный объект:
>>> 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) -
Удаляет указанные объекты модели из набора связанных объектов:
>>> 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) -
Удаляет все объекты из набора связанных объектов:
>>> 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) -
Заменяет набор связанных объектов:
>>> 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(),create(),remove(),clear(), иset()сразу применяют изменения в базе данных для всех типов связанных полей. Другими словами, нет необходимости вызыватьsave()на обоих концах отношения.Если вы используете
prefetch_related(), методыadd(),remove(),clear(), иset()очищают кэш предварительной выборки. -
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.1/ref/models/relations/