summaryrefslogtreecommitdiff
path: root/django/core/serializers/xml_serializer.py
diff options
context:
space:
mode:
authorChristopher Long <indirecthit@gmail.com>2007-06-17 22:18:54 +0000
committerChristopher Long <indirecthit@gmail.com>2007-06-17 22:18:54 +0000
commitae22b6d403dcf25098c77f0dfcf59ae58b186461 (patch)
treec37fc631e99a7e4d909d6b6d236f495003731ea7 /django/core/serializers/xml_serializer.py
parent0cf7bc439129c66df8d64601e885f83b256b4f25 (diff)
per-object-permissions: Merged to trunk [5486] NOTE: Not fully tested, will be working on this over the next few weeks.
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@5488 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core/serializers/xml_serializer.py')
-rw-r--r--django/core/serializers/xml_serializer.py58
1 files changed, 36 insertions, 22 deletions
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
index 512b8c6176..3e4a6f3e79 100644
--- a/django/core/serializers/xml_serializer.py
+++ b/django/core/serializers/xml_serializer.py
@@ -13,6 +13,10 @@ class Serializer(base.Serializer):
Serializes a QuerySet to XML.
"""
+ def indent(self, level):
+ if self.options.get('indent', None) is not None:
+ self.xml.ignorableWhitespace('\n' + ' ' * self.options.get('indent', None) * level)
+
def start_serialization(self):
"""
Start serialization -- open the XML document and the root element.
@@ -25,6 +29,7 @@ class Serializer(base.Serializer):
"""
End serialization -- end the document.
"""
+ self.indent(0)
self.xml.endElement("django-objects")
self.xml.endDocument()
@@ -35,6 +40,7 @@ class Serializer(base.Serializer):
if not hasattr(obj, "_meta"):
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
+ self.indent(1)
self.xml.startElement("object", {
"pk" : str(obj._get_pk_val()),
"model" : str(obj._meta),
@@ -44,6 +50,7 @@ class Serializer(base.Serializer):
"""
Called after handling all fields for an object.
"""
+ self.indent(1)
self.xml.endElement("object")
def handle_field(self, obj, field):
@@ -51,16 +58,19 @@ class Serializer(base.Serializer):
Called to handle each field on an object (except for ForeignKeys and
ManyToManyFields)
"""
+ self.indent(2)
self.xml.startElement("field", {
"name" : field.name,
"type" : field.get_internal_type()
})
# 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")
@@ -72,7 +82,13 @@ class Serializer(base.Serializer):
self._start_relational_field(field)
related = getattr(obj, field.name)
if related is not None:
- self.xml.characters(str(related._get_pk_val()))
+ if field.rel.field_name == related._meta.pk.name:
+ # Related to remote object via primary key
+ related = related._get_pk_val()
+ else:
+ # Related to remote object via other field
+ related = getattr(related, field.rel.field_name)
+ self.xml.characters(str(related))
else:
self.xml.addQuickElement("None")
self.xml.endElement("field")
@@ -92,6 +108,7 @@ class Serializer(base.Serializer):
"""
Helper to output the <field> element for relational fields
"""
+ self.indent(2)
self.xml.startElement("field", {
"name" : field.name,
"rel" : field.rel.__class__.__name__,
@@ -127,7 +144,8 @@ class Deserializer(base.Deserializer):
pk = node.getAttribute("pk")
if not pk:
raise base.DeserializationError("<object> 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,41 +166,37 @@ 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.name] = 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 <field> node for a ForeignKey
"""
- # Try to set the foreign key by looking up the foreign related object.
- # If it doesn't exist, set the field to None (which might trigger
- # validation error, but that's expected).
- RelatedModel = self._get_model_from_node(node, "to")
# Check if there is a child node named 'None', returning None if so.
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
return None
else:
- return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
+ return field.rel.to._meta.get_field(field.rel.field_name).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 <field> node for a ManyToManyField
"""
- # Load the related model
- RelatedModel = self._get_model_from_node(node, "to")
-
- # Look up all the related objects. Using the in_bulk() lookup ensures
- # that missing related objects don't cause an exception
- related_ids = [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")]
- return RelatedModel._default_manager.in_bulk(related_ids).values()
+ 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):
"""