Spec-Zone.ru › Django 1.9

Ссылка на связанные объекты

class 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 определяет, что поле Entry нового объекта blog должно быть установлено в 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, и поскольку blog ForeignKey не имеет 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(), и 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/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API