From 375c3edf6edc0bb9f3e726f67c70fa524556713b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 13 Mar 2007 00:59:34 +0000 Subject: [PATCH] Added various fixes to serializer implementations. Fixes mostly deal with handling nulls, non-integer primary key values (e.g., OneToOne fields or strings), and reconstruction of primary key references in related fields. git-svn-id: http://code.djangoproject.com/svn/django/trunk@4718 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/serializers/base.py | 6 +---- django/core/serializers/python.py | 9 ++++--- django/core/serializers/xml_serializer.py | 31 +++++++++++++++-------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 0ec05d1cf3..7dde2a4faf 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -54,11 +54,7 @@ class Serializer(object): Convert a field's value to a string. """ if isinstance(field, models.DateTimeField): - value = getattr(obj, field.name) - if value is None: - value = '' - else: - value = value.strftime("%Y-%m-%d %H:%M:%S") + value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S") elif isinstance(field, models.FileField): value = getattr(obj, "get_%s_url" % field.name, lambda: None)() else: diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index a9baa01d5a..29ce6bf9bd 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -57,7 +57,7 @@ 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 : d["pk"]} + data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} m2m_data = {} # Handle each field @@ -70,16 +70,17 @@ def Deserializer(object_list, **options): # Handle M2M relations if field.rel and isinstance(field.rel, models.ManyToManyRel): pks = [] + m2m_convert = field.rel.to._meta.pk.to_python for pk in field_value: if isinstance(pk, unicode): - pks.append(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))) + pks.append(m2m_convert(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))) else: - pks.append(pk) + pks.append(m2m_convert(pk)) m2m_data[field.name] = pks # Handle FK fields elif field.rel and isinstance(field.rel, models.ManyToOneRel): - data[field.attname] = field_value + data[field.attname] = field.rel.to._meta.pk.to_python(field_value) # Handle all other fields else: diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 8fa7bbfac9..9e37f03cc2 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -57,10 +57,12 @@ class Serializer(base.Serializer): }) # Get a "string version" of the object's data (this is handled by the - # serializer base class). None is handled specially. - value = self.get_string_value(obj, field) - if value is not None: + # serializer base class). + if getattr(obj, field.name) is not None: + value = self.get_string_value(obj, field) self.xml.characters(str(value)) + else: + self.xml.addQuickElement("None") self.xml.endElement("field") @@ -127,7 +129,8 @@ class Deserializer(base.Deserializer): pk = node.getAttribute("pk") if not pk: raise base.DeserializationError(" node is missing the 'pk' attribute") - data = {Model._meta.pk.name : pk} + + data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)} # Also start building a dict of m2m data (this is saved as # {m2m_accessor_attribute : [list_of_related_objects]}) @@ -148,17 +151,20 @@ class Deserializer(base.Deserializer): # As is usually the case, relation fields get the special treatment. if field.rel and isinstance(field.rel, models.ManyToManyRel): - m2m_data[field.name] = self._handle_m2m_field_node(field_node) + m2m_data[field.name] = self._handle_m2m_field_node(field_node, field) elif field.rel and isinstance(field.rel, models.ManyToOneRel): - data[field.attname] = self._handle_fk_field_node(field_node) + data[field.attname] = self._handle_fk_field_node(field_node, field) else: - value = field.to_python(getInnerText(field_node).strip().encode(self.encoding)) + if len(field_node.childNodes) == 1 and field_node.childNodes[0].nodeName == 'None': + value = None + else: + value = field.to_python(getInnerText(field_node).strip().encode(self.encoding)) data[field.name] = value # Return a DeserializedObject so that the m2m data has a place to live. return base.DeserializedObject(Model(**data), m2m_data) - def _handle_fk_field_node(self, node): + def _handle_fk_field_node(self, node, field): """ Handle a node for a ForeignKey """ @@ -166,13 +172,16 @@ class Deserializer(base.Deserializer): if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None': return None else: - return getInnerText(node).strip().encode(self.encoding) + return field.rel.to._meta.pk.to_python( + getInnerText(node).strip().encode(self.encoding)) - def _handle_m2m_field_node(self, node): + def _handle_m2m_field_node(self, node, field): """ Handle a node for a ManyToManyField """ - return [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")] + return [field.rel.to._meta.pk.to_python( + c.getAttribute("pk").encode(self.encoding)) + for c in node.getElementsByTagName("object")] def _get_model_from_node(self, node, attr): """