Работа со связанными объектами¶
- 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)¶
- 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(), а создает связывающие объекты с помощьюQuerySet.bulk_create(). Если вам необходима дополнительная логика при обновлении связей, обрабатывайте сигналm2m_changed.Использование
add()для уже существующего отношения не будет дублировать это отношение, но все равно будет вызывать сигналы.Для отношений «многие-ко-многим» add() принимает в качестве аргумента «*objs» либо экземпляры модели, либо значения полей, обычно первичные ключи.
Используйте аргумент
through_defaults, чтобы указать значения для нового экземпляра(ов) промежуточной модели <intermediary-manytomany>`, если необходимо. Вы можете использовать вызываемые объекты в качестве значений в словаре «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 самостоятельно определит, что полеblogнового объектаEntryдолжно содержать объектb.При необходимости используйте аргумент «through_defaults», чтобы указать значения для нового экземпляра промежуточной модели <intermediary-manytomany>. Вы можете использовать вызываемые объекты в качестве значений в словаре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, и так какForeignKeyвblogне содержитnull=True, это невозможно.Для объектов
ForeignKeyметод принимает аргументbulk, который определяет работу сохранения. Если указатьTrue(по умолчанию), будет использоватьсяQuerySet.update(). Приbulk=Falseбудет вызван методsave()для каждого объекта. Это вызывает сигналыpre_saveиpost_save, что работает немного медленне.Для отношений «многие-ко-многим» аргумент ключевого слова «bulk» не существует.
- clear(bulk=True)¶
- aclear(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)¶
- 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, чтобы указать значения для нового экземпляра(ов) промежуточной модели <intermediary-manytomany>`, если необходимо. Вы можете использовать вызываемые объекты в качестве значений в словаре «through_defaults», и они будут оценены один раз перед созданием каких-либо промежуточных экземпляров.
Примечание
Обратите внимание, что
add(),aadd(),create(),acreate(),remove(),aremove(),clear(),clear(),set()иaset()- все они немедленно применяют изменения базы данных для всех типов связанных полей. Другими словами, нет необходимости вызывать save()/asave() на любом конце отношения.Если вы используете
prefetch_based(), методыadd(),aadd(),remove(),aremove(),clear(),clear(),set()иaset()очищают предварительно загруженный кеш.