summaryrefslogtreecommitdiff
path: root/docs/ref/models/relations.txt
blob: 98177010b8c836ecee5899c1870db59091a45f9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
=========================
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 Blog(models.Model):
                # ...
                pass


            class Entry(models.Model):
                blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)

      In the above example, the methods below will be available on
      the manager ``blog.entry_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)
    .. method:: aadd(*objs, bulk=True, through_defaults=None)

        *Asynchronous version*: ``aadd``

        Adds the specified model objects to the related object set.

        Example:

        .. code-block:: pycon

            >>> 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.

        For many-to-many relationships ``add()`` accepts either model instances
        or field values, normally primary keys, as the ``*objs`` argument.

        Use the ``through_defaults`` argument to specify values for the new
        :ref:`intermediate model <intermediary-manytomany>` instance(s), if
        needed. You can use callables as values in the ``through_defaults``
        dictionary and they will be evaluated once before creating any
        intermediate instance(s).

        .. versionchanged:: 4.2

            ``aadd()`` method was added.

    .. method:: create(through_defaults=None, **kwargs)
    .. method:: acreate(through_defaults=None, **kwargs)

        *Asynchronous version*: ``acreate``

        Creates a new object, saves it and puts it in the related object set.
        Returns the newly created object:

        .. code-block:: pycon

            >>> 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):

        .. code-block:: pycon

            >>> 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. You can use callables as values in the ``through_defaults``
        dictionary.

    .. method:: remove(*objs, bulk=True)
    .. method:: aremove(*objs, bulk=True)

        *Asynchronous version*: ``aremove``

        Removes the specified model objects from the related object set:

        .. code-block:: pycon

            >>> 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.

        For many-to-many relationships ``remove()`` accepts either model
        instances or field values, normally primary keys, as the ``*objs``
        argument.

        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.

        .. versionchanged:: 4.2

            ``aremove()`` method was added.

    .. method:: clear(bulk=True)
    .. method:: aclear(bulk=True)

        *Asynchronous version*: ``aclear``

        Removes all objects from the related object set:

        .. code-block:: pycon

            >>> 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.

        .. versionchanged:: 4.2

            ``aclear()`` method was added.

    .. method:: set(objs, bulk=True, clear=False, through_defaults=None)
    .. method:: aset(objs, bulk=True, clear=False, through_defaults=None)

        *Asynchronous version*: ``aset``

        Replace the set of related objects:

        .. code-block:: pycon

            >>> 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()``.

        For many-to-many relationships ``set()`` accepts a list of either model
        instances or field values, normally primary keys, as the ``objs``
        argument.

        Use the ``through_defaults`` argument to specify values for the new
        :ref:`intermediate model <intermediary-manytomany>` instance(s), if
        needed. You can use callables as values in the ``through_defaults``
        dictionary and they will be evaluated once before creating any
        intermediate instance(s).

        .. versionchanged:: 4.2

            ``aset()`` method was added.

    .. note::

       Note that ``add()``, ``aadd()``, ``create()``, ``acreate()``,
       ``remove()``, ``aremove()``, ``clear()``, ``aclear()``, ``set()``, and
       ``aset()`` all apply database changes immediately for all types of
       related fields. In other words, there is no need to call
       ``save()``/``asave()`` on either end of the relationship.

       If you use :meth:`~django.db.models.query.QuerySet.prefetch_related`,
       the ``add()``, ``aadd()``, ``remove()``, ``aremove()``, ``clear()``,
       ``aclear()``, ``set()``, and ``aset()`` methods clear the prefetched
       cache.