summaryrefslogtreecommitdiffstats
path: root/webapp/django/core/serializers/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/django/core/serializers/base.py')
-rw-r--r--webapp/django/core/serializers/base.py175
1 files changed, 175 insertions, 0 deletions
diff --git a/webapp/django/core/serializers/base.py b/webapp/django/core/serializers/base.py
new file mode 100644
index 0000000000..bfd785a6fe
--- /dev/null
+++ b/webapp/django/core/serializers/base.py
@@ -0,0 +1,175 @@
+"""
+Module for abstract serializer/unserializer base classes.
+"""
+
+from StringIO import StringIO
+
+from django.db import models
+from django.utils.encoding import smart_str, smart_unicode
+from django.utils import datetime_safe
+
+class SerializationError(Exception):
+ """Something bad happened during serialization."""
+ pass
+
+class DeserializationError(Exception):
+ """Something bad happened during deserialization."""
+ pass
+
+class Serializer(object):
+ """
+ Abstract serializer base class.
+ """
+
+ # Indicates if the implemented serializer is only available for
+ # internal Django use.
+ internal_use_only = False
+
+ def serialize(self, queryset, **options):
+ """
+ Serialize a queryset.
+ """
+ self.options = options
+
+ self.stream = options.get("stream", StringIO())
+ self.selected_fields = options.get("fields")
+
+ self.start_serialization()
+ for obj in queryset:
+ self.start_object(obj)
+ for field in obj._meta.local_fields:
+ if field.serialize:
+ if field.rel is None:
+ if self.selected_fields is None or field.attname in self.selected_fields:
+ self.handle_field(obj, field)
+ else:
+ if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
+ self.handle_fk_field(obj, field)
+ for field in obj._meta.many_to_many:
+ if field.serialize:
+ if self.selected_fields is None or field.attname in self.selected_fields:
+ self.handle_m2m_field(obj, field)
+ self.end_object(obj)
+ self.end_serialization()
+ return self.getvalue()
+
+ def get_string_value(self, obj, field):
+ """
+ Convert a field's value to a string.
+ """
+ if isinstance(field, models.DateTimeField):
+ d = datetime_safe.new_datetime(getattr(obj, field.name))
+ value = d.strftime("%Y-%m-%d %H:%M:%S")
+ else:
+ value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
+ return smart_unicode(value)
+
+ def start_serialization(self):
+ """
+ Called when serializing of the queryset starts.
+ """
+ raise NotImplementedError
+
+ def end_serialization(self):
+ """
+ Called when serializing of the queryset ends.
+ """
+ pass
+
+ def start_object(self, obj):
+ """
+ Called when serializing of an object starts.
+ """
+ raise NotImplementedError
+
+ def end_object(self, obj):
+ """
+ Called when serializing of an object ends.
+ """
+ pass
+
+ def handle_field(self, obj, field):
+ """
+ Called to handle each individual (non-relational) field on an object.
+ """
+ raise NotImplementedError
+
+ def handle_fk_field(self, obj, field):
+ """
+ Called to handle a ForeignKey field.
+ """
+ raise NotImplementedError
+
+ def handle_m2m_field(self, obj, field):
+ """
+ Called to handle a ManyToManyField.
+ """
+ raise NotImplementedError
+
+ def getvalue(self):
+ """
+ Return the fully serialized queryset (or None if the output stream is
+ not seekable).
+ """
+ if callable(getattr(self.stream, 'getvalue', None)):
+ return self.stream.getvalue()
+
+class Deserializer(object):
+ """
+ Abstract base deserializer class.
+ """
+
+ def __init__(self, stream_or_string, **options):
+ """
+ Init this serializer given a stream or a string
+ """
+ self.options = options
+ if isinstance(stream_or_string, basestring):
+ self.stream = StringIO(stream_or_string)
+ else:
+ self.stream = stream_or_string
+ # hack to make sure that the models have all been loaded before
+ # deserialization starts (otherwise subclass calls to get_model()
+ # and friends might fail...)
+ models.get_apps()
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """Iteration iterface -- return the next item in the stream"""
+ raise NotImplementedError
+
+class DeserializedObject(object):
+ """
+ A deserialized model.
+
+ Basically a container for holding the pre-saved deserialized data along
+ with the many-to-many data saved with the object.
+
+ Call ``save()`` to save the object (with the many-to-many data) to the
+ database; call ``save(save_m2m=False)`` to save just the object fields
+ (and not touch the many-to-many stuff.)
+ """
+
+ def __init__(self, obj, m2m_data=None):
+ self.object = obj
+ self.m2m_data = m2m_data
+
+ def __repr__(self):
+ return "<DeserializedObject: %s>" % smart_str(self.object)
+
+ def save(self, save_m2m=True):
+ # Call save on the Model baseclass directly. This bypasses any
+ # model-defined save. The save is also forced to be raw.
+ # This ensures that the data that is deserialized is literally
+ # what came from the file, not post-processed by pre_save/save
+ # methods.
+ models.Model.save_base(self.object, raw=True)
+ if self.m2m_data and save_m2m:
+ for accessor_name, object_list in self.m2m_data.items():
+ setattr(self.object, accessor_name, object_list)
+
+ # prevent a second (possibly accidental) call to save() from saving
+ # the m2m data twice.
+ self.m2m_data = None