summaryrefslogtreecommitdiff
path: root/django/core/serializers/python.py
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2006-11-06 21:11:49 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2006-11-06 21:11:49 +0000
commitdc59c670b8cbe055ff3565f8d5a2f600c5ab1ba8 (patch)
tree84a2d1a3e729a813cf692ebbe7404ba8e5687d22 /django/core/serializers/python.py
parentbf629e5a4d1a51f938c84d35d768830158ad5ebd (diff)
Merged to [3519]
git-svn-id: http://code.djangoproject.com/svn/django/branches/generic-auth@4024 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core/serializers/python.py')
-rw-r--r--django/core/serializers/python.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
new file mode 100644
index 0000000000..4181bc7f2b
--- /dev/null
+++ b/django/core/serializers/python.py
@@ -0,0 +1,101 @@
+"""
+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
+
+class Serializer(base.Serializer):
+ """
+ Serializes a QuerySet to basic Python objects.
+ """
+
+ 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" : str(obj._meta),
+ "pk" : str(obj._get_pk_val()),
+ "fields" : self._current
+ })
+ self._current = None
+
+ def handle_field(self, obj, field):
+ self._current[field.name] = getattr(obj, field.name)
+
+ def handle_fk_field(self, obj, field):
+ related = getattr(obj, field.name)
+ if related is not None:
+ related = related._get_pk_val()
+ self._current[field.name] = related
+
+ def handle_m2m_field(self, obj, field):
+ self._current[field.name] = [related._get_pk_val() 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.name : d["pk"]}
+ m2m_data = {}
+
+ # Handle each field
+ for (field_name, field_value) in d["fields"].iteritems():
+ if isinstance(field_value, unicode):
+ field_value = field_value.encode(options.get("encoding", settings.DEFAULT_CHARSET))
+
+ field = Model._meta.get_field(field_name)
+
+ # Handle M2M relations (with in_bulk() for performance)
+ if field.rel and isinstance(field.rel, models.ManyToManyRel):
+ pks = []
+ for pk in field_value:
+ if isinstance(pk, unicode):
+ pk = pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))
+ m2m_data[field.name] = field.rel.to._default_manager.in_bulk(field_value).values()
+
+ # Handle FK fields
+ elif field.rel and isinstance(field.rel, models.ManyToOneRel):
+ try:
+ data[field.name] = field.rel.to._default_manager.get(pk=field_value)
+ except field.rel.to.DoesNotExist:
+ data[field.name] = 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("Invalid model identifier: '%s'" % model_identifier)
+ return Model