Ссылка на связанные объекты
-
«Связанный менеджер» — это менеджер, используемый в контексте связи «один ко многим» или «многие ко многим». Это происходит в двух случаях:
-
«Другая сторона» связи
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.
-
Добавляет указанные объекты модели в набор связанных объектов.
Пример:
>>> 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, если вам требуется старое поведение.
-
Создаёт новый объект, сохраняет его и помещает в набор связанных объектов. Возвращает только что созданный объект:
>>> 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.
-
Удаляет указанные объекты модели из набора связанных объектов:
>>> 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, и посколькуblogForeignKeyне имеетnull=True, это недействительно.Для объектов
ForeignKeyэтот метод принимает аргументbulkдля управления способом выполнения операции. ЕслиTrue(по умолчанию), используетсяQuerySet.update(). Еслиbulk=False, вместо этого вызывается методsave()каждого отдельного экземпляра модели. Это запускает сигналыpre_saveиpost_saveи влечёт за собой снижение производительности.
-
Удаляет все объекты из набора связанных объектов:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
Обратите внимание, что это не удаляет связанные объекты — это просто отсоединяет их.
Как и
remove(),clear()доступен только дляForeignKeyсnull=True, и он также принимает ключевой аргументbulk.
-
Заменяет набор связанных объектов:
>>> 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(), иset()все сразу применяют изменения в базе данных для всех типов связанных полей. Другими словами, нет необходимости вызыватьsave()на обоих концах связи.Также, если вы используете промежуточную модель для связи «многие ко многим», то методы
add(),create(),remove(), иset()отключены. -
Прямая присваивание
Связанный набор объектов можно заменить оптом одной операцией, присвоив ему новый итерируемый набор объектов:
>>> new_list = [obj1, obj2, obj3] >>> e.related_set = new_list
Если связь внешнего ключа имеет null=True, связанный менеджер сначала отсоединит все существующие объекты в связанном наборе перед добавлением содержимого new_list. В противном случае объекты в new_list будут добавлены к существующему связанному набору объектов.
В предыдущих версиях прямое присваивание выполняло clear() за которым следовало add(). Теперь оно выполняет set() с ключевым аргументом clear=False.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.9/ref/models/relations/