diff options
| author | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-11-06 21:11:49 +0000 |
|---|---|---|
| committer | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-11-06 21:11:49 +0000 |
| commit | dc59c670b8cbe055ff3565f8d5a2f600c5ab1ba8 (patch) | |
| tree | 84a2d1a3e729a813cf692ebbe7404ba8e5687d22 /django/core/serializers/python.py | |
| parent | bf629e5a4d1a51f938c84d35d768830158ad5ebd (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.py | 101 |
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 |
