summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPeter Inglesby <peter.inglesby@gmail.com>2018-07-13 22:54:47 +0100
committerTim Graham <timograham@gmail.com>2018-07-13 17:54:47 -0400
commit312eb5cb11d09c0c41b2740e2e9aef838d60c8b5 (patch)
tree00dec6ddb620204930bc2c870e1bb73c5bb87973 /docs
parent8f75d21a2e6d255848ae441d858c6ea819e3d100 (diff)
Fixed #26291 -- Allowed loaddata to handle forward references in natural_key fixtures.
Diffstat (limited to 'docs')
-rw-r--r--docs/releases/2.2.txt5
-rw-r--r--docs/topics/serialization.txt65
2 files changed, 62 insertions, 8 deletions
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 3d1f2783ab..ce8bcd6fa4 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -184,7 +184,10 @@ Requests and Responses
Serialization
~~~~~~~~~~~~~
-* ...
+* You can now deserialize data using natural keys containing :ref:`forward
+ references <natural-keys-and-forward-references>` by passing
+ ``handle_forward_references=True`` to ``serializers.deserialize()``.
+ Additionally, :djadmin:`loaddata` handles forward references automatically.
Signals
~~~~~~~
diff --git a/docs/topics/serialization.txt b/docs/topics/serialization.txt
index 58a00bec20..433fb23718 100644
--- a/docs/topics/serialization.txt
+++ b/docs/topics/serialization.txt
@@ -514,17 +514,68 @@ command line flags to generate natural keys.
natural keys during serialization, but *not* be able to load those
key values, just don't define the ``get_by_natural_key()`` method.
+.. _natural-keys-and-forward-references:
+
+Natural keys and forward references
+-----------------------------------
+
+.. versionadded:: 2.2
+
+Sometimes when you use :ref:`natural foreign keys
+<topics-serialization-natural-keys>` you'll need to deserialize data where
+an object has a foreign key referencing another object that hasn't yet been
+deserialized. This is called a "forward reference".
+
+For instance, suppose you have the following objects in your fixture::
+
+ ...
+ {
+ "model": "store.book",
+ "fields": {
+ "name": "Mostly Harmless",
+ "author": ["Douglas", "Adams"]
+ }
+ },
+ ...
+ {
+ "model": "store.person",
+ "fields": {
+ "first_name": "Douglas",
+ "last_name": "Adams"
+ }
+ },
+ ...
+
+In order to handle this situation, you need to pass
+``handle_forward_references=True`` to ``serializers.deserialize()``. This will
+set the ``deferred_fields`` attribute on the ``DeserializedObject`` instances.
+You'll need to keep track of ``DeserializedObject`` instances where this
+attribute isn't ``None`` and later call ``save_deferred_fields()`` on them.
+
+Typical usage looks like this::
+
+ objs_with_deferred_fields = []
+
+ for obj in serializers.deserialize('xml', data, handle_forward_references=True):
+ obj.save()
+ if obj.deferred_fields is not None:
+ objs_with_deferred_fields.append(obj)
+
+ for obj in objs_with_deferred_fields:
+ obj.save_deferred_fields()
+
+For this to work, the ``ForeignKey`` on the referencing model must have
+``null=True``.
+
Dependencies during serialization
---------------------------------
-Since natural keys rely on database lookups to resolve references, it
-is important that the data exists before it is referenced. You can't make
-a "forward reference" with natural keys -- the data you're referencing
-must exist before you include a natural key reference to that data.
+It's often possible to avoid explicitly having to handle forward references by
+taking care with the ordering of objects within a fixture.
-To accommodate this limitation, calls to :djadmin:`dumpdata` that use
-the :option:`dumpdata --natural-foreign` option will serialize any model with a
-``natural_key()`` method before serializing standard primary key objects.
+To help with this, calls to :djadmin:`dumpdata` that use the :option:`dumpdata
+--natural-foreign` option will serialize any model with a ``natural_key()``
+method before serializing standard primary key objects.
However, this may not always be enough. If your natural key refers to
another object (by using a foreign key or natural key to another object