Работа со связанными объектами¶
- 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.
Both sides of a
ManyToManyFieldrelation: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(), а создает связывающие объекты с помощьюQuerySet.bulk_create(). Если вам необходима дополнительная логика при обновлении связей, обрабатывайте сигналm2m_changed.Использование
add()для уже существующего отношения не будет дублировать это отношение, но все равно будет вызывать сигналы.Для отношений «многие-ко-многим» add() принимает в качестве аргумента «*objs» либо экземпляры модели, либо значения полей, обычно первичные ключи.
Используйте аргумент
through_defaults, чтобы указать значения для нового экземпляра(ов) промежуточной модели <intermediary-manytomany>`, если необходимо. Вы можете использовать вызываемые объекты в качестве значений в словаре «through_defaults», и они будут оценены один раз перед созданием каких-либо промежуточных экземпляров.Changed in Django 3.1:through_defaultsvalues can now be callables.
- create(through_defaults=None, **kwargs)¶
Creates a new object, saves it and puts it in the related object set. Returns the newly created object:
>>> 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.
This is equivalent to (but simpler than):
>>> 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 самостоятельно определит, что полеblogнового объектаEntryдолжно содержать объектb.При необходимости используйте аргумент «through_defaults», чтобы указать значения для нового экземпляра промежуточной модели <intermediary-manytomany>. Вы можете использовать вызываемые объекты в качестве значений в словареthrough_defaults.
Changed in Django 3.1:through_defaultsvalues can now be callables.
- remove(*objs, bulk=True)¶
Removes the specified model objects from the related object set:
>>> 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, и так какForeignKeyвblogне содержитnull=True, это невозможно.Для объектов
ForeignKeyметод принимает аргументbulk, который определяет работу сохранения. Если указатьTrue(по умолчанию), будет использоватьсяQuerySet.update(). Приbulk=Falseбудет вызван методsave()для каждого объекта. Это вызывает сигналыpre_saveиpost_save, что работает немного медленне.Для отношений «многие-ко-многим» аргумент ключевого слова «bulk» не существует.
- clear(bulk=True)¶
Removes all objects from the related object set:
>>> 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)¶
Replace the set of related objects:
>>> 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, чтобы указать значения для нового экземпляра(ов) промежуточной модели <intermediary-manytomany>`, если необходимо. Вы можете использовать вызываемые объекты в качестве значений в словаре «through_defaults», и они будут оценены один раз перед созданием каких-либо промежуточных экземпляров.Changed in Django 3.1:through_defaultsvalues can now be callables.
Примечание
Note that
add(),create(),remove(),clear(), andset()all apply database changes immediately for all types of related fields. In other words, there is no need to callsave()on either end of the relationship.If you use
prefetch_related(), theadd(),remove(),clear(), andset()methods clear the prefetched cache.