web/lib/django/core/serializers/base.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 """
       
     2 Module for abstract serializer/unserializer base classes.
       
     3 """
       
     4 
       
     5 from StringIO import StringIO
       
     6 
       
     7 from django.db import models
       
     8 from django.utils.encoding import smart_str, smart_unicode
       
     9 from django.utils import datetime_safe
       
    10 
       
    11 class SerializationError(Exception):
       
    12     """Something bad happened during serialization."""
       
    13     pass
       
    14 
       
    15 class DeserializationError(Exception):
       
    16     """Something bad happened during deserialization."""
       
    17     pass
       
    18 
       
    19 class Serializer(object):
       
    20     """
       
    21     Abstract serializer base class.
       
    22     """
       
    23 
       
    24     # Indicates if the implemented serializer is only available for
       
    25     # internal Django use.
       
    26     internal_use_only = False
       
    27 
       
    28     def serialize(self, queryset, **options):
       
    29         """
       
    30         Serialize a queryset.
       
    31         """
       
    32         self.options = options
       
    33 
       
    34         self.stream = options.get("stream", StringIO())
       
    35         self.selected_fields = options.get("fields")
       
    36         self.use_natural_keys = options.get("use_natural_keys", False)
       
    37 
       
    38         self.start_serialization()
       
    39         for obj in queryset:
       
    40             self.start_object(obj)
       
    41             for field in obj._meta.local_fields:
       
    42                 if field.serialize:
       
    43                     if field.rel is None:
       
    44                         if self.selected_fields is None or field.attname in self.selected_fields:
       
    45                             self.handle_field(obj, field)
       
    46                     else:
       
    47                         if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
       
    48                             self.handle_fk_field(obj, field)
       
    49             for field in obj._meta.many_to_many:
       
    50                 if field.serialize:
       
    51                     if self.selected_fields is None or field.attname in self.selected_fields:
       
    52                         self.handle_m2m_field(obj, field)
       
    53             self.end_object(obj)
       
    54         self.end_serialization()
       
    55         return self.getvalue()
       
    56 
       
    57     def get_string_value(self, obj, field):
       
    58         """
       
    59         Convert a field's value to a string.
       
    60         """
       
    61         return smart_unicode(field.value_to_string(obj))
       
    62 
       
    63     def start_serialization(self):
       
    64         """
       
    65         Called when serializing of the queryset starts.
       
    66         """
       
    67         raise NotImplementedError
       
    68 
       
    69     def end_serialization(self):
       
    70         """
       
    71         Called when serializing of the queryset ends.
       
    72         """
       
    73         pass
       
    74 
       
    75     def start_object(self, obj):
       
    76         """
       
    77         Called when serializing of an object starts.
       
    78         """
       
    79         raise NotImplementedError
       
    80 
       
    81     def end_object(self, obj):
       
    82         """
       
    83         Called when serializing of an object ends.
       
    84         """
       
    85         pass
       
    86 
       
    87     def handle_field(self, obj, field):
       
    88         """
       
    89         Called to handle each individual (non-relational) field on an object.
       
    90         """
       
    91         raise NotImplementedError
       
    92 
       
    93     def handle_fk_field(self, obj, field):
       
    94         """
       
    95         Called to handle a ForeignKey field.
       
    96         """
       
    97         raise NotImplementedError
       
    98 
       
    99     def handle_m2m_field(self, obj, field):
       
   100         """
       
   101         Called to handle a ManyToManyField.
       
   102         """
       
   103         raise NotImplementedError
       
   104 
       
   105     def getvalue(self):
       
   106         """
       
   107         Return the fully serialized queryset (or None if the output stream is
       
   108         not seekable).
       
   109         """
       
   110         if callable(getattr(self.stream, 'getvalue', None)):
       
   111             return self.stream.getvalue()
       
   112 
       
   113 class Deserializer(object):
       
   114     """
       
   115     Abstract base deserializer class.
       
   116     """
       
   117 
       
   118     def __init__(self, stream_or_string, **options):
       
   119         """
       
   120         Init this serializer given a stream or a string
       
   121         """
       
   122         self.options = options
       
   123         if isinstance(stream_or_string, basestring):
       
   124             self.stream = StringIO(stream_or_string)
       
   125         else:
       
   126             self.stream = stream_or_string
       
   127         # hack to make sure that the models have all been loaded before
       
   128         # deserialization starts (otherwise subclass calls to get_model()
       
   129         # and friends might fail...)
       
   130         models.get_apps()
       
   131 
       
   132     def __iter__(self):
       
   133         return self
       
   134 
       
   135     def next(self):
       
   136         """Iteration iterface -- return the next item in the stream"""
       
   137         raise NotImplementedError
       
   138 
       
   139 class DeserializedObject(object):
       
   140     """
       
   141     A deserialized model.
       
   142 
       
   143     Basically a container for holding the pre-saved deserialized data along
       
   144     with the many-to-many data saved with the object.
       
   145 
       
   146     Call ``save()`` to save the object (with the many-to-many data) to the
       
   147     database; call ``save(save_m2m=False)`` to save just the object fields
       
   148     (and not touch the many-to-many stuff.)
       
   149     """
       
   150 
       
   151     def __init__(self, obj, m2m_data=None):
       
   152         self.object = obj
       
   153         self.m2m_data = m2m_data
       
   154 
       
   155     def __repr__(self):
       
   156         return "<DeserializedObject: %s.%s(pk=%s)>" % (
       
   157             self.object._meta.app_label, self.object._meta.object_name, self.object.pk)
       
   158 
       
   159     def save(self, save_m2m=True, using=None):
       
   160         # Call save on the Model baseclass directly. This bypasses any
       
   161         # model-defined save. The save is also forced to be raw.
       
   162         # This ensures that the data that is deserialized is literally
       
   163         # what came from the file, not post-processed by pre_save/save
       
   164         # methods.
       
   165         models.Model.save_base(self.object, using=using, raw=True)
       
   166         if self.m2m_data and save_m2m:
       
   167             for accessor_name, object_list in self.m2m_data.items():
       
   168                 setattr(self.object, accessor_name, object_list)
       
   169 
       
   170         # prevent a second (possibly accidental) call to save() from saving
       
   171         # the m2m data twice.
       
   172         self.m2m_data = None