RelatedManager
¶“Менеджер связанных объектов” – это менеджер, который используется для связей один-ко-многим и многие-ко-многим. Это происходит в двух случаях:
“Обратная связь” для ForeignKey
. Например:
from django.db import models
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
В этом примере, методы описанные ниже будут доступны через менеджер reporter.article_set
.
Для обоих сторон связи через ManyToManyField
:
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
В этом примере, методы описанные ниже будут доступны для менеджеров topping.pizza_set
и pizza.toppings
.
add
(*objs, bulk=True)¶Добавляет указанный объект модели к множеству связанных объектов.
Например:
>>> 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
.
Был добавлен аргумент bulk
. В предыдущих версих обновления внешнего ключа всегда выполнялось с помощью save()
. Используйте bulk=False
для предыдущего поведения.
create
(**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
.
remove
(*objs)¶Удаляет указанный объект из списка связанных объектов:
>>> 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
.
Метод существует только для 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
, что работает немного медленне.
clear
()¶Удаляет все объекты из списка связанных:
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
Заметим, что связанные объекты не удаляются – просто разрывается связь.
Так же как и remove()
, clear()
доступен только для ForeignKey
с null=True
и принимает аргумент bulk
.
set
(objs, bulk=True, clear=False)¶Удаляет все объекты из списка связанных:
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
Этот метод принимает аргумент clear
, чтобы управлять выполнение операции. При False
(по умолчанию), объекты, которые отсутствуют в новом множестве, будут удалены с помощью команды remove()
, и только новые объекты будут добавлены. При clear=True
, вызывается метод clear()
и все множество добавляет за раз.
Аргумент bulk
передается в add()
.
Обратите внимание, т.к. set()
составная операция, она подвержена состоянию гонки. Например, в базу данных могут быть добавлены новые объекты между вызовами clear()
и add()
.
Примечание
Обратите внимание, add()
, create()
, remove()
и clear()
сразу сохраняют изменения для всех типов связей. Другими словами, нет необходимости вызывать save()
.
Также, если вы используете промежуточную модель для связи многое ко многим, некоторые методы могут быть не доступны.
Список связанных объектов можно поменять одной операцией, назначив список объектов:
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list
Если внешний ключ определен с null=True
, сначала будут удалены все связанные объекты перед добавлением объектов из new_list
. Иначе объекты из new_list
будут добавлены к списку существующих объектов.
В предыдущих версиях при прямом присваивании вызывался метод clear()
и затем add()
. Теперь используется метод set()
с аргументом clear=False
.
_meta
APIВведите слова для поиска или имя модуля, класса или функции.
Jun 05, 2017