Fixed #13418 -- Added notes on uniqueness requirements for natural keys. Thanks to hunajakippo for the suggestion, and Ramiro Morales for the draft text.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13146 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e7e46d1f4b
commit
5a2324afb2
|
@ -197,6 +197,7 @@ 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.
|
||||||
|
|
||||||
|
@ -219,13 +220,13 @@ 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
|
||||||
more natural reference would be helpful.
|
more natural reference would be helpful.
|
||||||
|
|
||||||
Deserialization of natural keys
|
It is for these reasons that Django provides *natural keys*. A natural
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
It is for these reasons that Django provides `natural keys`. A natural
|
|
||||||
key is a tuple of values that can be used to uniquely identify an
|
key is a tuple of values that can be used to uniquely identify an
|
||||||
object instance without using the primary key value.
|
object instance without using the primary key value.
|
||||||
|
|
||||||
|
Deserialization of natural keys
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Consider the following two models::
|
Consider the following two models::
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
@ -236,6 +237,9 @@ Consider the following two models::
|
||||||
|
|
||||||
birthdate = models.DateField()
|
birthdate = models.DateField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = (('first_name', 'last_name'),)
|
||||||
|
|
||||||
class Book(models.Model):
|
class Book(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
author = models.ForeignKey(Person)
|
author = models.ForeignKey(Person)
|
||||||
|
@ -278,6 +282,9 @@ name::
|
||||||
|
|
||||||
birthdate = models.DateField()
|
birthdate = models.DateField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = (('first_name', 'last_name'),)
|
||||||
|
|
||||||
Now books can use that natural key to refer to ``Person`` objects::
|
Now books can use that natural key to refer to ``Person`` objects::
|
||||||
|
|
||||||
...
|
...
|
||||||
|
@ -295,6 +302,17 @@ When you try to load this serialized data, Django will use the
|
||||||
``get_by_natural_key()`` method to resolve ``["Douglas", "Adams"]``
|
``get_by_natural_key()`` method to resolve ``["Douglas", "Adams"]``
|
||||||
into the primary key of an actual ``Person`` object.
|
into the primary key of an actual ``Person`` object.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Whatever fields you use for a natural key must be able to uniquely
|
||||||
|
identify an object. This will usually mean that your model will
|
||||||
|
have a uniqueness clause (either unique=True on a single field, or
|
||||||
|
``unique_together`` over multiple fields) for the field or fields
|
||||||
|
in your natural key. However, uniqueness doesn't need to be
|
||||||
|
enforced at the database level. If you are certain that a set of
|
||||||
|
fields will be effectively unique, you can still use those fields
|
||||||
|
as a natural key.
|
||||||
|
|
||||||
Serialization of natural keys
|
Serialization of natural keys
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -312,8 +330,13 @@ Firstly, you need to add another method -- this time to the model itself::
|
||||||
def natural_key(self):
|
def natural_key(self):
|
||||||
return (self.first_name, self.last_name)
|
return (self.first_name, self.last_name)
|
||||||
|
|
||||||
Then, when you call ``serializers.serialize()``, you provide a
|
class Meta:
|
||||||
``use_natural_keys=True`` argument::
|
unique_together = (('first_name', 'last_name'),)
|
||||||
|
|
||||||
|
That method should always return a natural key tuple -- in this
|
||||||
|
example, ``(first name, last name)``. Then, when you call
|
||||||
|
``serializers.serialize()``, you provide a ``use_natural_keys=True``
|
||||||
|
argument::
|
||||||
|
|
||||||
>>> serializers.serialize([book1, book2], format='json', indent=2, use_natural_keys=True)
|
>>> serializers.serialize([book1, book2], format='json', indent=2, use_natural_keys=True)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue