Ticket #13252: 13252.2.diff

File 13252.2.diff, 4.8 KB (added by Chris Beaven, 9 years ago)
  • django/core/serializers/base.py

    diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
    index 190636e..9f535e3 100644
    a b class DeserializedObject(object): 
    170170        # prevent a second (possibly accidental) call to save() from saving
    171171        # the m2m data twice.
    172172        self.m2m_data = None
     173
     174def build_instance(Model, data, db):
     175    """
     176    Build a model instance.
     177
     178    If the model instance doesn't have a primary key and the model supports
     179    natural keys, try to retrieve it from the database.
     180    """
     181    obj = Model(**data)
     182    if obj.pk is None and hasattr(Model, 'natural_key') and\
     183            hasattr(Model._default_manager, 'get_by_natural_key'):
     184        pk = obj.natural_key()
     185        try:
     186            obj.pk = Model._default_manager.db_manager(db)\
     187                                           .get_by_natural_key(*pk).pk
     188        except Model.DoesNotExist:
     189            pass
     190    return obj
  • django/core/serializers/python.py

    diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
    index a68ea21..e557008 100644
    a b class Serializer(base.Serializer): 
    2727        self._current = {}
    2828
    2929    def end_object(self, obj):
    30         self.objects.append({
    31             "model"  : smart_unicode(obj._meta),
    32             "pk"     : smart_unicode(obj._get_pk_val(), strings_only=True),
    33             "fields" : self._current
    34         })
     30        data = {
     31            "model": smart_unicode(obj._meta),
     32            "fields": self._current
     33        }
     34        if not self.use_natural_keys or not hasattr(obj, 'natural_key'):
     35            data['pk'] = smart_unicode(obj._get_pk_val(), strings_only=True)
     36        self.objects.append(data)
    3537        self._current = None
    3638
    3739    def handle_field(self, obj, field):
    def Deserializer(object_list, **options): 
    8284    for d in object_list:
    8385        # Look up the model and starting build a dict of data for it.
    8486        Model = _get_model(d["model"])
    85         data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
     87        data = {}
     88        if 'pk' in d:
     89            data[Model._meta.pk.attname] = d['pk']
    8690        m2m_data = {}
    8791
    8892        # Handle each field
    def Deserializer(object_list, **options): 
    127131            else:
    128132                data[field.name] = field.to_python(field_value)
    129133
    130         yield base.DeserializedObject(Model(**data), m2m_data)
     134        obj = base.build_instance(Model, data, db)
     135
     136        yield base.DeserializedObject(obj, m2m_data)
    131137
    132138def _get_model(model_identifier):
    133139    """
  • django/core/serializers/xml_serializer.py

    diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
    index 5fef3b6..a7d5218 100644
    a b class Serializer(base.Serializer): 
    4242            raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
    4343
    4444        self.indent(1)
    45         self.xml.startElement("object", {
    46             "pk"    : smart_unicode(obj._get_pk_val()),
    47             "model" : smart_unicode(obj._meta),
    48         })
     45        object_data = {"model": smart_unicode(obj._meta)}
     46        if not self.use_natural_keys or not hasattr(obj, 'natural_key'):
     47            object_data['pk'] = smart_unicode(obj._get_pk_val())
     48        self.xml.startElement("object", object_data)
    4949
    5050    def end_object(self, obj):
    5151        """
    class Deserializer(base.Deserializer): 
    166166        # bail.
    167167        Model = self._get_model_from_node(node, "model")
    168168
    169         # Start building a data dictionary from the object.  If the node is
    170         # missing the pk attribute, bail.
    171         pk = node.getAttribute("pk")
    172         if not pk:
    173             raise base.DeserializationError("<object> node is missing the 'pk' attribute")
    174 
    175         data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
     169        # Start building a data dictionary from the object.
     170        data = {}
     171        if node.hasAttribute('pk'):
     172            pk = node.getAttribute("pk")
     173            data[Model._meta.pk.attname] = node.Model._meta.pk.to_python(pk)
    176174
    177175        # Also start building a dict of m2m data (this is saved as
    178176        # {m2m_accessor_attribute : [list_of_related_objects]})
    class Deserializer(base.Deserializer): 
    203201                    value = field.to_python(getInnerText(field_node).strip())
    204202                data[field.name] = value
    205203
     204        obj = base.build_instance(Model, data, self.db)
     205
    206206        # Return a DeserializedObject so that the m2m data has a place to live.
    207         return base.DeserializedObject(Model(**data), m2m_data)
     207        return base.DeserializedObject(obj, m2m_data)
    208208
    209209    def _handle_fk_field_node(self, node, field):
    210210        """
Back to Top