1
0
mirror of https://github.com/django/django.git synced 2024-12-24 18:16:19 +00:00
django/docs/ref/models/relations.txt
Tobias Kunze 4a954cfd11 Fixed #30573 -- Rephrased documentation to avoid words that minimise the involved difficulty.
This patch does not remove all occurrences of the words in question.
Rather, I went through all of the occurrences of the words listed
below, and judged if they a) suggested the reader had some kind of
knowledge/experience, and b) if they added anything of value (including
tone of voice, etc). I left most of the words alone. I looked at the
following words:

- simply/simple
- easy/easier/easiest
- obvious
- just
- merely
- straightforward
- ridiculous

Thanks to Carlton Gibson for guidance on how to approach this issue, and
to Tim Bell for providing the idea. But the enormous lion's share of
thanks go to Adam Johnson for his patient and helpful review.
2019-09-06 13:27:46 +02:00

220 lines
8.7 KiB
Plaintext

=========================
Related objects reference
=========================
.. currentmodule:: django.db.models.fields.related
.. class:: RelatedManager
A "related manager" is a manager used in a one-to-many or many-to-many
related context. This happens in two cases:
* The "other side" of a :class:`~django.db.models.ForeignKey` relation.
That is::
from django.db import models
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
In the above example, the methods below will be available on
the manager ``reporter.article_set``.
* Both sides of a :class:`~django.db.models.ManyToManyField` relation::
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
In this example, the methods below will be available both on
``topping.pizza_set`` and on ``pizza.toppings``.
.. method:: add(*objs, bulk=True, through_defaults=None)
Adds the specified model objects to the related object set.
Example::
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.
In the example above, in the case of a
:class:`~django.db.models.ForeignKey` relationship,
:meth:`QuerySet.update() <django.db.models.query.QuerySet.update>`
is used to perform the update. This requires the objects to already be
saved.
You can use the ``bulk=False`` argument to instead have the related
manager perform the update by calling ``e.save()``.
Using ``add()`` with a many-to-many relationship, however, will not
call any ``save()`` methods (the ``bulk`` argument doesn't exist), but
rather create the relationships using :meth:`QuerySet.bulk_create()
<django.db.models.query.QuerySet.bulk_create>`. If you need to execute
some custom logic when a relationship is created, listen to the
:data:`~django.db.models.signals.m2m_changed` signal, which will
trigger ``pre_add`` and ``post_add`` actions.
Using ``add()`` on a relation that already exists won't duplicate the
relation, but it will still trigger signals.
``add()`` also accepts the field the relation points to as an argument.
The above example can be rewritten as ``b.entry_set.add(234)``.
Use the ``through_defaults`` argument to specify values for the new
:ref:`intermediate model <intermediary-manytomany>` instance(s), if
needed.
.. versionchanged:: 2.2
The ``through_defaults`` argument was added.
.. method:: create(through_defaults=None, **kwargs)
Creates a new object, saves it and puts it in the related object set.
Returns the newly created object::
>>> 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.
This is equivalent to (but simpler than)::
>>> 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)
Note that there's no need to specify the keyword argument of the model
that defines the relationship. In the above example, we don't pass the
parameter ``blog`` to ``create()``. Django figures out that the new
``Entry`` object's ``blog`` field should be set to ``b``.
Use the ``through_defaults`` argument to specify values for the new
:ref:`intermediate model <intermediary-manytomany>` instance, if
needed.
.. versionchanged:: 2.2
The ``through_defaults`` argument was added.
.. method:: remove(*objs, bulk=True)
Removes the specified model objects from the related object set::
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
Similar to :meth:`add()`, ``e.save()`` is called in the example above
to perform the update. Using ``remove()`` with a many-to-many
relationship, however, will delete the relationships using
:meth:`QuerySet.delete()<django.db.models.query.QuerySet.delete>` which
means no model ``save()`` methods are called; listen to the
:data:`~django.db.models.signals.m2m_changed` signal if you wish to
execute custom code when a relationship is deleted.
Similarly to :meth:`add()`, ``remove()`` also accepts the field the
relation points to as an argument. The above example can be rewritten
as ``b.entry_set.remove(234)``.
For :class:`~django.db.models.ForeignKey` objects, this method only
exists if ``null=True``. If the related field can't be set to ``None``
(``NULL``), then an object can't be removed from a relation without
being added to another. In the above example, removing ``e`` from
``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because
the ``blog`` :class:`~django.db.models.ForeignKey` doesn't have
``null=True``, this is invalid.
For :class:`~django.db.models.ForeignKey` objects, this method accepts
a ``bulk`` argument to control how to perform the operation.
If ``True`` (the default), ``QuerySet.update()`` is used.
If ``bulk=False``, the ``save()`` method of each individual model
instance is called instead. This triggers the
:data:`~django.db.models.signals.pre_save` and
:data:`~django.db.models.signals.post_save` signals and comes at the
expense of performance.
For many-to-many relationships, the ``bulk`` keyword argument doesn't
exist.
.. method:: clear(bulk=True)
Removes all objects from the related object set::
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
Note this doesn't delete the related objects -- it just disassociates
them.
Just like ``remove()``, ``clear()`` is only available on
:class:`~django.db.models.ForeignKey`\s where ``null=True`` and it also
accepts the ``bulk`` keyword argument.
For many-to-many relationships, the ``bulk`` keyword argument doesn't
exist.
.. method:: set(objs, bulk=True, clear=False, through_defaults=None)
Replace the set of related objects::
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
This method accepts a ``clear`` argument to control how to perform the
operation. If ``False`` (the default), the elements missing from the
new set are removed using ``remove()`` and only the new ones are added.
If ``clear=True``, the ``clear()`` method is called instead and the
whole set is added at once.
For :class:`~django.db.models.ForeignKey` objects, the ``bulk``
argument is passed on to :meth:`add` and :meth:`remove`.
For many-to-many relationships, the ``bulk`` keyword argument doesn't
exist.
Note that since ``set()`` is a compound operation, it is subject to
race conditions. For instance, new objects may be added to the database
in between the call to ``clear()`` and the call to ``add()``.
Similarly to :meth:`add()`, ``set()`` also accepts the field the
relation points to as an argument. The above example can be rewritten
as ``e.related_set.set([obj1.pk, obj2.pk, obj3.pk])``.
Use the ``through_defaults`` argument to specify values for the new
:ref:`intermediate model <intermediary-manytomany>` instance(s), if
needed.
.. versionchanged:: 2.2
The ``through_defaults`` argument was added.
.. note::
Note that ``add()``, ``create()``, ``remove()``, ``clear()``, and
``set()`` all apply database changes immediately for all types of
related fields. In other words, there is no need to call ``save()``
on either end of the relationship.
If you use :meth:`~django.db.models.query.QuerySet.prefetch_related`,
the ``add()``, ``remove()``, ``clear()``, and ``set()`` methods clear
the prefetched cache.