diff options
| author | Chris Beaven <smileychris@gmail.com> | 2010-12-21 04:40:08 +0000 |
|---|---|---|
| committer | Chris Beaven <smileychris@gmail.com> | 2010-12-21 04:40:08 +0000 |
| commit | b60d5df07266dd4cd4f63afa6986ffb2932facc2 (patch) | |
| tree | a08f75ea3485e70b5b18bde8ea7d44414b78a0bc /django | |
| parent | c2657d892396c51448432637a855eb9ecac5363c (diff) | |
Fixes #13252 -- Use the natural key instead of the primary key when serializing
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14994 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/serializers/base.py | 18 | ||||
| -rw-r--r-- | django/core/serializers/python.py | 20 | ||||
| -rw-r--r-- | django/core/serializers/xml_serializer.py | 31 |
3 files changed, 44 insertions, 25 deletions
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 190636e670..9f535e3ba8 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -170,3 +170,21 @@ class DeserializedObject(object): # prevent a second (possibly accidental) call to save() from saving # the m2m data twice. self.m2m_data = None + +def build_instance(Model, data, db): + """ + Build a model instance. + + If the model instance doesn't have a primary key and the model supports + natural keys, try to retrieve it from the database. + """ + obj = Model(**data) + if obj.pk is None and hasattr(Model, 'natural_key') and\ + hasattr(Model._default_manager, 'get_by_natural_key'): + pk = obj.natural_key() + try: + obj.pk = Model._default_manager.db_manager(db)\ + .get_by_natural_key(*pk).pk + except Model.DoesNotExist: + pass + return obj diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index a68ea21f78..839fee12a9 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -27,11 +27,13 @@ class Serializer(base.Serializer): self._current = {} def end_object(self, obj): - self.objects.append({ - "model" : smart_unicode(obj._meta), - "pk" : smart_unicode(obj._get_pk_val(), strings_only=True), - "fields" : self._current - }) + data = { + "model": smart_unicode(obj._meta), + "fields": self._current + } + if not self.use_natural_keys or not hasattr(obj, 'natural_key'): + data['pk'] = smart_unicode(obj._get_pk_val(), strings_only=True) + self.objects.append(data) self._current = None def handle_field(self, obj, field): @@ -82,7 +84,9 @@ def Deserializer(object_list, **options): for d in object_list: # Look up the model and starting build a dict of data for it. Model = _get_model(d["model"]) - data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} + data = {} + if 'pk' in d: + data[Model._meta.pk.attname] = Model._meta.pk.to_python(d['pk']) m2m_data = {} # Handle each field @@ -127,7 +131,9 @@ def Deserializer(object_list, **options): else: data[field.name] = field.to_python(field_value) - yield base.DeserializedObject(Model(**data), m2m_data) + obj = base.build_instance(Model, data, db) + + yield base.DeserializedObject(obj, m2m_data) def _get_model(model_identifier): """ diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index bcf5631e00..36e3404988 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -42,16 +42,12 @@ class Serializer(base.Serializer): raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) self.indent(1) - obj_pk = obj._get_pk_val() - if obj_pk is None: - attrs = {"model": smart_unicode(obj._meta),} - else: - attrs = { - "pk": smart_unicode(obj._get_pk_val()), - "model": smart_unicode(obj._meta), - } - - self.xml.startElement("object", attrs) + object_data = {"model": smart_unicode(obj._meta)} + if not self.use_natural_keys or not hasattr(obj, 'natural_key'): + obj_pk = obj._get_pk_val() + if obj_pk is not None: + object_data['pk'] = smart_unicode(obj_pk) + self.xml.startElement("object", object_data) def end_object(self, obj): """ @@ -173,13 +169,10 @@ class Deserializer(base.Deserializer): Model = self._get_model_from_node(node, "model") # Start building a data dictionary from the object. - # If the node is missing the pk set it to None - if node.hasAttribute("pk"): - pk = node.getAttribute("pk") - else: - pk = None - - data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)} + data = {} + if node.hasAttribute('pk'): + data[Model._meta.pk.attname] = Model._meta.pk.to_python( + node.getAttribute('pk')) # Also start building a dict of m2m data (this is saved as # {m2m_accessor_attribute : [list_of_related_objects]}) @@ -210,8 +203,10 @@ class Deserializer(base.Deserializer): value = field.to_python(getInnerText(field_node).strip()) data[field.name] = value + obj = base.build_instance(Model, data, self.db) + # Return a DeserializedObject so that the m2m data has a place to live. - return base.DeserializedObject(Model(**data), m2m_data) + return base.DeserializedObject(obj, m2m_data) def _handle_fk_field_node(self, node, field): """ |
