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:
parent
c51c9b3ce6
commit
d101ed2cb8
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue