Доступ к связанным объектам


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 выясняет, что в поле blog нового объекта Entry следует установить значение 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, и потому что ``blog ForeignKey не имеет ``null=``True, это недопустимо.

Для объектов ForeignKey этот метод принимает аргумент объемный для управления тем, как выполнять операцию. Если 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() очищают предварительно загруженный кеш.