Fixed #16364 -- Clarified why automatically created data shouldn't be saved in fixtures. Thanks Gabriel for the review.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17355 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Aymeric Augustin 2012-01-07 21:52:07 +00:00
parent c51c9b3ce6
commit d101ed2cb8
1 changed files with 40 additions and 35 deletions

View File

@ -198,23 +198,32 @@ Natural keys
------------ ------------
.. versionadded:: 1.2 .. versionadded:: 1.2
The ability to use natural keys when serializing/deserializing data was The ability to use natural keys when serializing/deserializing data was
added in the 1.2 release. added in the 1.2 release.
The default serialization strategy for foreign keys and many-to-many The default serialization strategy for foreign keys and many-to-many relations
relations is to serialize the value of the primary key(s) of the is to serialize the value of the primary key(s) of the objects in the relation.
objects in the relation. This strategy works well for most types of This strategy works well for most objects, but it can cause difficulty in some
object, but it can cause difficulty in some circumstances. circumstances.
Consider the case of a list of objects that have foreign key on Consider the case of a list of objects that have a foreign key referencing
:class:`ContentType`. If you're going to serialize an object that :class:`~django.contrib.conttenttypes.models.ContentType`. If you're going to
refers to a content type, you need to have a way to refer to that serialize an object that refers to a content type, then you need to have a way
content type. Content Types are automatically created by Django as to refer to that content type to begin with. Since ``ContentType`` objects are
part of the database synchronization process, so you don't need to automatically created by Django during the database synchronization process,
include content types in a fixture or other serialized data. As a the primary key of a given content type isn't easy to predict; it will
result, the primary key of any given content type isn't easy to depend on how and when :djadmin:`syncdb` was executed. This is true for all
predict - it will depend on how and when :djadmin:`syncdb` was models which automatically generate objects, notably including
executed to create the content types. :class:`~django.contrib.auth.models.Permission`.
.. warning::
You should never include automatically generated objects in a fixture or
other serialized data. By chance, the primary keys in the fixture
may match those in the database and loading the fixture will
have no effect. In the more likely case that they don't match, the fixture
loading will fail with an :class:`~django.db.IntegrityError`.
There is also the matter of convenience. An integer id isn't always There is also the matter of convenience. An integer id isn't always
the most convenient way to refer to an object; sometimes, a the most convenient way to refer to an object; sometimes, a
@ -363,13 +372,13 @@ Dependencies during serialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since natural keys rely on database lookups to resolve references, it Since natural keys rely on database lookups to resolve references, it
is important that data exists before it is referenced. You can't make is important that the data exists before it is referenced. You can't make
a `forward reference` with natural keys - the data you are referencing a `forward reference` with natural keys--the data you are referencing
must exist before you include a natural key reference to that data. must exist before you include a natural key reference to that data.
To accommodate this limitation, calls to :djadmin:`dumpdata` that use To accommodate this limitation, calls to :djadmin:`dumpdata` that use
the :djadminopt:`--natural` option will serialize any model with a the :djadminopt:`--natural` option will serialize any model with a
``natural_key()`` method before it serializes normal key objects. ``natural_key()`` method before serializing standard primary key objects.
However, this may not always be enough. If your natural key refers to 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 another object (by using a foreign key or natural key to another object
@ -381,28 +390,24 @@ To control this ordering, you can define dependencies on your
``natural_key()`` methods. You do this by setting a ``dependencies`` ``natural_key()`` methods. You do this by setting a ``dependencies``
attribute on the ``natural_key()`` method itself. attribute on the ``natural_key()`` method itself.
For example, consider the ``Permission`` model in ``contrib.auth``. For example, let's add a natural key to the ``Book`` model from the
The following is a simplified version of the ``Permission`` model:: example above::
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person)
class Permission(models.Model):
name = models.CharField(max_length=50)
content_type = models.ForeignKey(ContentType)
codename = models.CharField(max_length=100)
# ...
def natural_key(self): def natural_key(self):
return (self.codename,) + self.content_type.natural_key() return (self.name,) + self.author.natural_key()
The natural key for a ``Permission`` is a combination of the codename for the The natural key for a ``Book`` is a combination of its name and its
``Permission``, and the ``ContentType`` to which the ``Permission`` applies. This means author. This means that ``Person`` must be serialized before ``Book``.
that ``ContentType`` must be serialized before ``Permission``. To define this To define this dependency, we add one extra line::
dependency, we add one extra line::
class Permission(models.Model):
# ...
def natural_key(self): def natural_key(self):
return (self.codename,) + self.content_type.natural_key() return (self.name,) + self.author.natural_key()
natural_key.dependencies = ['contenttypes.contenttype'] natural_key.dependencies = ['example_app.person']
This definition ensures that ``ContentType`` models are serialized before This definition ensures that all ``Person`` objects are serialized before
``Permission`` models. In turn, any object referencing ``Permission`` will any ``Book`` objects. In turn, any object referencing ``Book`` will be
be serialized after both ``ContentType`` and ``Permission``. serialized after both ``Person`` and ``Book`` have been serialized.