diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
index 190636e..9f535e3 100644
a
|
b
|
class DeserializedObject(object):
|
170 | 170 | # prevent a second (possibly accidental) call to save() from saving |
171 | 171 | # the m2m data twice. |
172 | 172 | self.m2m_data = None |
| 173 | |
| 174 | def 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 |
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
index a68ea21..e557008 100644
a
|
b
|
class Serializer(base.Serializer):
|
27 | 27 | self._current = {} |
28 | 28 | |
29 | 29 | 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) |
35 | 37 | self._current = None |
36 | 38 | |
37 | 39 | def handle_field(self, obj, field): |
… |
… |
def Deserializer(object_list, **options):
|
82 | 84 | for d in object_list: |
83 | 85 | # Look up the model and starting build a dict of data for it. |
84 | 86 | 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'] |
86 | 90 | m2m_data = {} |
87 | 91 | |
88 | 92 | # Handle each field |
… |
… |
def Deserializer(object_list, **options):
|
127 | 131 | else: |
128 | 132 | data[field.name] = field.to_python(field_value) |
129 | 133 | |
130 | | yield base.DeserializedObject(Model(**data), m2m_data) |
| 134 | obj = base.build_instance(Model, data, db) |
| 135 | |
| 136 | yield base.DeserializedObject(obj, m2m_data) |
131 | 137 | |
132 | 138 | def _get_model(model_identifier): |
133 | 139 | """ |
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):
|
42 | 42 | raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) |
43 | 43 | |
44 | 44 | 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) |
49 | 49 | |
50 | 50 | def end_object(self, obj): |
51 | 51 | """ |
… |
… |
class Deserializer(base.Deserializer):
|
166 | 166 | # bail. |
167 | 167 | Model = self._get_model_from_node(node, "model") |
168 | 168 | |
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) |
176 | 174 | |
177 | 175 | # Also start building a dict of m2m data (this is saved as |
178 | 176 | # {m2m_accessor_attribute : [list_of_related_objects]}) |
… |
… |
class Deserializer(base.Deserializer):
|
203 | 201 | value = field.to_python(getInnerText(field_node).strip()) |
204 | 202 | data[field.name] = value |
205 | 203 | |
| 204 | obj = base.build_instance(Model, data, self.db) |
| 205 | |
206 | 206 | # 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) |
208 | 208 | |
209 | 209 | def _handle_fk_field_node(self, node, field): |
210 | 210 | """ |