--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/core/serializers/python.py Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,107 @@
+"""
+A Python "serializer". Doesn't do much serializing per se -- just converts to
+and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for
+other serializers.
+"""
+
+from django.conf import settings
+from django.core.serializers import base
+from django.db import models
+from django.utils.encoding import smart_unicode
+
+class Serializer(base.Serializer):
+ """
+ Serializes a QuerySet to basic Python objects.
+ """
+
+ internal_use_only = True
+
+ def start_serialization(self):
+ self._current = None
+ self.objects = []
+
+ def end_serialization(self):
+ pass
+
+ def start_object(self, obj):
+ 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
+ })
+ self._current = None
+
+ def handle_field(self, obj, field):
+ self._current[field.name] = smart_unicode(getattr(obj, field.name), strings_only=True)
+
+ def handle_fk_field(self, obj, field):
+ related = getattr(obj, field.name)
+ if related is not None:
+ 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._current[field.name] = smart_unicode(related, strings_only=True)
+
+ def handle_m2m_field(self, obj, field):
+ self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True)
+ for related in getattr(obj, field.name).iterator()]
+
+ def getvalue(self):
+ return self.objects
+
+def Deserializer(object_list, **options):
+ """
+ Deserialize simple Python objects back into Django ORM instances.
+
+ It's expected that you pass the Python objects themselves (instead of a
+ stream or a string) to the constructor
+ """
+ models.get_apps()
+ 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"])}
+ m2m_data = {}
+
+ # Handle each field
+ for (field_name, field_value) in d["fields"].iteritems():
+ if isinstance(field_value, str):
+ field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
+
+ field = Model._meta.get_field(field_name)
+
+ # Handle M2M relations
+ if field.rel and isinstance(field.rel, models.ManyToManyRel):
+ m2m_convert = field.rel.to._meta.pk.to_python
+ m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value]
+
+ # Handle FK fields
+ elif field.rel and isinstance(field.rel, models.ManyToOneRel):
+ if field_value:
+ data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
+ else:
+ data[field.attname] = None
+
+ # Handle all other fields
+ else:
+ data[field.name] = field.to_python(field_value)
+
+ yield base.DeserializedObject(Model(**data), m2m_data)
+
+def _get_model(model_identifier):
+ """
+ Helper to look up a model from an "app_label.module_name" string.
+ """
+ try:
+ Model = models.get_model(*model_identifier.split("."))
+ except TypeError:
+ Model = None
+ if Model is None:
+ raise base.DeserializationError(u"Invalid model identifier: '%s'" % model_identifier)
+ return Model