summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorLoic Bistuer <loic.bistuer@gmail.com>2015-01-30 01:15:27 +0700
committerLoic Bistuer <loic.bistuer@gmail.com>2015-02-05 12:45:08 +0700
commit71ada3a8e689a883b5ffdeb1744ea16f176ab730 (patch)
tree7e4696ec75370e0747a26c4dea541626573895b2 /docs
parent49516f7158ed0ca39ea8116d25a32a80288d47b3 (diff)
Fixed #6707 -- Added RelatedManager.set() and made descriptors' __set__ use it.
Thanks Anssi Kääriäinen, Carl Meyer, Collin Anderson, and Tim Graham for the reviews.
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/models/relations.txt39
-rw-r--r--docs/releases/1.9.txt24
-rw-r--r--docs/topics/db/queries.txt3
3 files changed, 58 insertions, 8 deletions
diff --git a/docs/ref/models/relations.txt b/docs/ref/models/relations.txt
index 7f5eb18ea6..8c3b5a2f33 100644
--- a/docs/ref/models/relations.txt
+++ b/docs/ref/models/relations.txt
@@ -135,12 +135,31 @@ Related objects reference
:class:`~django.db.models.ForeignKey`\s where ``null=True`` and it also
accepts the ``bulk`` keyword argument.
+ .. method:: set(objs, clear=False)
+
+ .. versionadded:: 1.9
+
+ 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.
+
+ 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()``.
+
.. note::
- Note that ``add()``, ``create()``, ``remove()``, and ``clear()`` 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.
+ 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.
Also, if you are using :ref:`an intermediate model
<intermediary-manytomany>` for a many-to-many relationship, some of the
@@ -158,6 +177,12 @@ new iterable of objects to it::
>>> e.related_set = new_list
If the foreign key relationship has ``null=True``, then the related manager
-will first call ``clear()`` to disassociate any existing objects in the related
-set before adding the contents of ``new_list``. Otherwise the objects in
-``new_list`` will be added to the existing related object set.
+will first disassociate any existing objects in the related set before adding
+the contents of ``new_list``. Otherwise the objects in ``new_list`` will be
+added to the existing related object set.
+
+.. versionchanged:1.9
+
+ In earlier versions, direct assignment used to perform ``clear()`` followed
+ by ``add()``. It now performs a ``set()`` with the keyword argument
+ ``clear=False``.
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index eee63c6f6d..d00bfef096 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -127,7 +127,10 @@ Management Commands
Models
^^^^^^
-* ...
+* Added the :meth:`RelatedManager.set()
+ <django.db.models.fields.related.RelatedManager.set()>` method to the related
+ managers created by ``ForeignKey``, ``GenericForeignKey``, and
+ ``ManyToManyField``.
Signals
^^^^^^^
@@ -192,6 +195,25 @@ used by the egg loader to detect if setuptools was installed. The ``is_usable``
attribute is now removed and the egg loader instead fails at runtime if
setuptools is not installed.
+Related set direct assignment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:ref:`Direct assignment <direct-assignment>`) used to perform a ``clear()``
+followed by a call to ``add()``. This caused needlessly large data changes
+and prevented using the :data:`~django.db.models.signals.m2m_changed` signal
+to track individual changes in many-to-many relations.
+
+Direct assignment now relies on the the new
+:meth:`django.db.models.fields.related.RelatedManager.set()` method on
+related managers which by default only processes changes between the
+existing related set and the one that's newly assigned. The previous behavior
+can be restored by replacing direct assignment by a call to ``set()`` with
+the keyword argument ``clear=True``.
+
+``ModelForm``, and therefore ``ModelAdmin``, internally rely on direct
+assignment for many-to-many relations and as a consequence now use the new
+behavior.
+
Miscellaneous
~~~~~~~~~~~~~
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index c616d02b33..34342ab3eb 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -1190,6 +1190,9 @@ be found in the :doc:`related objects reference </ref/models/relations>`.
``clear()``
Removes all objects from the related object set.
+``set(objs)``
+ Replace the set of related objects.
+
To assign the members of a related set in one fell swoop, just assign to it
from any iterable object. The iterable can contain object instances, or just
a list of primary key values. For example::