Changeset 5248
- Timestamp:
- 05/15/07 11:14:55 (1 year ago)
- Files:
-
- django/branches/unicode/django/core/serializers/base.py (modified) (3 diffs)
- django/branches/unicode/django/core/serializers/__init__.py (modified) (3 diffs)
- django/branches/unicode/django/core/serializers/python.py (modified) (7 diffs)
- django/branches/unicode/django/core/serializers/pyyaml.py (modified) (2 diffs)
- django/branches/unicode/django/core/serializers/xml_serializer.py (modified) (17 diffs)
- django/branches/unicode/tests/regressiontests/serializers_regress/tests.py (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/unicode/django/core/serializers/base.py
r5081 r5248 8 8 from StringIO import StringIO 9 9 from django.db import models 10 from django.utils.encoding import smart_str, smart_unicode 10 11 11 12 class SerializationError(Exception): … … 60 61 else: 61 62 value = field.flatten_data(follow=None, obj=obj).get(field.name, "") 62 return s tr(value)63 return smart_unicode(value) 63 64 64 65 def start_serialization(self): … … 155 156 156 157 def __repr__(self): 157 return "<DeserializedObject: %s>" % s tr(self.object)158 return "<DeserializedObject: %s>" % smart_str(self.object) 158 159 159 160 def save(self, save_m2m=True): django/branches/unicode/django/core/serializers/__init__.py
r4712 r5248 7 7 >>> json = serializers.serialize("json", some_query_set) 8 8 >>> objects = list(serializers.deserialize("json", json)) 9 9 10 10 To add your own serializers, use the SERIALIZATION_MODULES setting:: 11 11 … … 31 31 BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml" 32 32 except ImportError: 33 pass 33 pass 34 34 35 35 _serializers = {} 36 36 37 37 def register_serializer(format, serializer_module): 38 38 """Register a new serializer by passing in a module name.""" 39 39 module = __import__(serializer_module, {}, {}, ['']) 40 40 _serializers[format] = module 41 41 42 42 def unregister_serializer(format): 43 43 """Unregister a given serializer""" 44 44 del _serializers[format] 45 45 46 46 def get_serializer(format): 47 47 if not _serializers: … … 53 53 _load_serializers() 54 54 return _serializers.keys() 55 55 56 56 def get_deserializer(format): 57 57 if not _serializers: 58 58 _load_serializers() 59 59 return _serializers[format].Deserializer 60 60 61 61 def serialize(format, queryset, **options): 62 62 """ django/branches/unicode/django/core/serializers/python.py
r5241 r5248 8 8 from django.core.serializers import base 9 9 from django.db import models 10 from django.utils.encoding import smart_unicode 10 11 11 12 class Serializer(base.Serializer): … … 13 14 Serializes a QuerySet to basic Python objects. 14 15 """ 15 16 16 17 def start_serialization(self): 17 18 self._current = None 18 19 self.objects = [] 19 20 20 21 def end_serialization(self): 21 22 pass 22 23 23 24 def start_object(self, obj): 24 25 self._current = {} 25 26 26 27 def end_object(self, obj): 27 28 self.objects.append({ 28 "model" : s tr(obj._meta),29 "pk" : s tr(obj._get_pk_val()),29 "model" : smart_unicode(obj._meta), 30 "pk" : smart_unicode(obj._get_pk_val()), 30 31 "fields" : self._current 31 32 }) 32 33 self._current = None 33 34 34 35 def handle_field(self, obj, field): 35 36 self._current[field.name] = getattr(obj, field.name) 36 37 37 38 def handle_fk_field(self, obj, field): 38 39 related = getattr(obj, field.name) … … 40 41 related = getattr(related, field.rel.field_name) 41 42 self._current[field.name] = related 42 43 43 44 def handle_m2m_field(self, obj, field): 44 45 self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()] 45 46 46 47 def getvalue(self): 47 48 return self.objects … … 50 51 """ 51 52 Deserialize simple Python objects back into Django ORM instances. 52 53 53 54 It's expected that you pass the Python objects themselves (instead of a 54 55 stream or a string) to the constructor … … 60 61 data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} 61 62 m2m_data = {} 62 63 63 64 # Handle each field 64 65 for (field_name, field_value) in d["fields"].iteritems(): 65 if isinstance(field_value, unicode):66 field_value = field_value.encode(options.get("encoding", settings.DEFAULT_CHARSET))67 66 if isinstance(field_value, str): 67 field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET)) 68 68 69 field = Model._meta.get_field(field_name) 69 70 70 71 # Handle M2M relations 71 72 if field.rel and isinstance(field.rel, models.ManyToManyRel): 72 pks = []73 73 m2m_convert = field.rel.to._meta.pk.to_python 74 for pk in field_value: 75 if isinstance(pk, unicode): 76 pks.append(m2m_convert(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))) 77 else: 78 pks.append(m2m_convert(pk)) 79 m2m_data[field.name] = pks 80 74 m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value] 75 81 76 # Handle FK fields 82 77 elif field.rel and isinstance(field.rel, models.ManyToOneRel): … … 85 80 else: 86 81 data[field.attname] = None 87 82 88 83 # Handle all other fields 89 84 else: 90 85 data[field.name] = field.to_python(field_value) 91 86 92 87 yield base.DeserializedObject(Model(**data), m2m_data) 93 88 … … 101 96 Model = None 102 97 if Model is None: 103 raise base.DeserializationError( "Invalid model identifier: '%s'" % model_identifier)98 raise base.DeserializationError(u"Invalid model identifier: '%s'" % model_identifier) 104 99 return Model django/branches/unicode/django/core/serializers/pyyaml.py
r4734 r5248 20 20 def end_serialization(self): 21 21 yaml.dump(self.objects, self.stream, **self.options) 22 22 23 23 def getvalue(self): 24 24 return self.stream.getvalue() … … 34 34 for obj in PythonDeserializer(yaml.load(stream)): 35 35 yield obj 36 36 django/branches/unicode/django/core/serializers/xml_serializer.py
r5241 r5248 7 7 from django.db import models 8 8 from django.utils.xmlutils import SimplerXMLGenerator 9 from django.utils.encoding import smart_unicode 9 10 from xml.dom import pulldom 10 11 … … 13 14 Serializes a QuerySet to XML. 14 15 """ 15 16 16 17 def indent(self, level): 17 18 if self.options.get('indent', None) is not None: … … 25 26 self.xml.startDocument() 26 27 self.xml.startElement("django-objects", {"version" : "1.0"}) 27 28 28 29 def end_serialization(self): 29 30 """ … … 33 34 self.xml.endElement("django-objects") 34 35 self.xml.endDocument() 35 36 36 37 def start_object(self, obj): 37 38 """ … … 40 41 if not hasattr(obj, "_meta"): 41 42 raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) 42 43 43 44 self.indent(1) 44 45 self.xml.startElement("object", { 45 "pk" : s tr(obj._get_pk_val()),46 "model" : s tr(obj._meta),46 "pk" : smart_unicode(obj._get_pk_val()), 47 "model" : smart_unicode(obj._meta), 47 48 }) 48 49 49 50 def end_object(self, obj): 50 51 """ … … 53 54 self.indent(1) 54 55 self.xml.endElement("object") 55 56 56 57 def handle_field(self, obj, field): 57 58 """ … … 64 65 "type" : field.get_internal_type() 65 66 }) 66 67 67 68 # Get a "string version" of the object's data (this is handled by the 68 # serializer base class). 69 # serializer base class). 69 70 if getattr(obj, field.name) is not None: 70 71 value = self.get_string_value(obj, field) 71 self.xml.characters(s tr(value))72 self.xml.characters(smart_unicode(value)) 72 73 else: 73 74 self.xml.addQuickElement("None") 74 75 75 76 self.xml.endElement("field") 76 77 77 78 def handle_fk_field(self, obj, field): 78 79 """ … … 83 84 related = getattr(obj, field.name) 84 85 if related is not None: 85 self.xml.characters(s tr(getattr(related, field.rel.field_name)))86 self.xml.characters(smart_unicode(getattr(related, field.rel.field_name))) 86 87 else: 87 88 self.xml.addQuickElement("None") 88 89 self.xml.endElement("field") 89 90 90 91 def handle_m2m_field(self, obj, field): 91 92 """ … … 96 97 self._start_relational_field(field) 97 98 for relobj in getattr(obj, field.name).iterator(): 98 self.xml.addQuickElement("object", attrs={"pk" : s tr(relobj._get_pk_val())})99 self.xml.addQuickElement("object", attrs={"pk" : smart_unicode(relobj._get_pk_val())}) 99 100 self.xml.endElement("field") 100 101 101 102 def _start_relational_field(self, field): 102 103 """ … … 107 108 "name" : field.name, 108 109 "rel" : field.rel.__class__.__name__, 109 "to" : s tr(field.rel.to._meta),110 "to" : smart_unicode(field.rel.to._meta), 110 111 }) 111 112 112 113 class Deserializer(base.Deserializer): 113 114 """ 114 115 Deserialize XML. 115 116 """ 116 117 117 118 def __init__(self, stream_or_string, **options): 118 119 super(Deserializer, self).__init__(stream_or_string, **options) 119 self.encoding = self.options.get("encoding", settings.DEFAULT_CHARSET) 120 self.event_stream = pulldom.parse(self.stream) 121 120 self.event_stream = pulldom.parse(self.stream) 121 122 122 def next(self): 123 123 for event, node in self.event_stream: … … 126 126 return self._handle_object(node) 127 127 raise StopIteration 128 128 129 129 def _handle_object(self, node): 130 130 """ 131 131 Convert an <object> node to a DeserializedObject. 132 132 """ 133 # Look up the model using the model loading mechanism. If this fails, bail. 133 # Look up the model using the model loading mechanism. If this fails, 134 # bail. 134 135 Model = self._get_model_from_node(node, "model") 135 136 136 137 # Start building a data dictionary from the object. If the node is 137 138 # missing the pk attribute, bail. … … 141 142 142 143 data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)} 143 144 144 145 # Also start building a dict of m2m data (this is saved as 145 146 # {m2m_accessor_attribute : [list_of_related_objects]}) 146 147 m2m_data = {} 147 148 148 149 # Deseralize each field. 149 150 for field_node in node.getElementsByTagName("field"): … … 153 154 if not field_name: 154 155 raise base.DeserializationError("<field> node is missing the 'name' attribute") 155 156 156 157 # Get the field from the Model. This will raise a 157 158 # FieldDoesNotExist if, well, the field doesn't exist, which will 158 159 # be propagated correctly. 159 160 field = Model._meta.get_field(field_name) 160 161 161 162 # As is usually the case, relation fields get the special treatment. 162 163 if field.rel and isinstance(field.rel, models.ManyToManyRel): … … 168 169 value = None 169 170 else: 170 value = field.to_python(getInnerText(field_node).strip() .encode(self.encoding))171 value = field.to_python(getInnerText(field_node).strip()) 171 172 data[field.name] = value 172 173 173 174 # Return a DeserializedObject so that the m2m data has a place to live. 174 175 return base.DeserializedObject(Model(**data), m2m_data) 175 176 176 177 def _handle_fk_field_node(self, node, field): 177 178 """ … … 183 184 else: 184 185 return field.rel.to._meta.get_field(field.rel.field_name).to_python( 185 getInnerText(node).strip() .encode(self.encoding))186 186 getInnerText(node).strip()) 187 187 188 def _handle_m2m_field_node(self, node, field): 188 189 """ 189 Handle a <field> node for a ManyToManyField 190 Handle a <field> node for a ManyToManyField. 190 191 """ 191 192 return [field.rel.to._meta.pk.to_python( 192 c.getAttribute("pk") .encode(self.encoding))193 c.getAttribute("pk")) 193 194 for c in node.getElementsByTagName("object")] 194 195 195 196 def _get_model_from_node(self, node, attr): 196 197 """ … … 212 213 (node.nodeName, model_identifier)) 213 214 return Model 214 215 215 216 216 217 def getInnerText(node): 217 218 """ … … 227 228 else: 228 229 pass 229 return "".join(inner_text) 230 return u"".join(inner_text) 231 django/branches/unicode/tests/regressiontests/serializers_regress/tests.py
r5241 r5248 3 3 4 4 This class defines sample data and a dynamically generated 5 test case that is capable of testing the capabilities of 5 test case that is capable of testing the capabilities of 6 6 the serializers. This includes all valid data values, plus 7 7 forward, backwards and self references. … … 23 23 instance = klass(id=pk) 24 24 instance.data = data 25 instance.save() 25 instance.save() 26 26 return instance 27 27 … … 33 33 instance.tags.create(data=tag) 34 34 return instance 35 35 36 36 def fk_create(pk, klass, data): 37 37 instance = klass(id=pk) … … 39 39 instance.save() 40 40 return instance 41 41 42 42 def m2m_create(pk, klass, data): 43 43 instance = klass(id=pk) … … 62 62 def data_compare(testcase, pk, klass, data): 63 63 instance = klass.objects.get(id=pk) 64 testcase.assertEqual(data, instance.data, 64 testcase.assertEqual(data, instance.data, 65 65 "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) 66 66 … … 69 69 testcase.assertEqual(data[0], instance.data) 70 70 testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()]) 71 71 72 72 def fk_compare(testcase, pk, klass, data): 73 73 instance = klass.objects.get(id=pk) … … 85 85 instance = klass.objects.get(data=data) 86 86 testcase.assertEqual(data, instance.data) 87 87 88 88 # Define some data types. Each data type is 89 89 # actually a pair of functions; one to create … … 97 97 98 98 test_data = [ 99 # Format: (data type, PK value, Model Class, data) 99 # Format: (data type, PK value, Model Class, data) 100 100 (data_obj, 1, BooleanData, True), 101 101 (data_obj, 2, BooleanData, False), … … 106 106 (data_obj, 14, CharData, "NULL"), 107 107 (data_obj, 15, CharData, None), 108 # (We use something that will fit into a latin1 database encoding here, 109 # because that is still the default used on many system setups.) 110 (data_obj, 16, CharData, u'\xa5'), 108 111 (data_obj, 20, DateData, datetime.date(2006,6,16)), 109 112 (data_obj, 21, DateData, None), … … 138 141 (data_obj, 140, SlugData, "this-is-a-slug"), 139 142 (data_obj, 141, SlugData, None), 140 (data_obj, 150, SmallData, 12), 141 (data_obj, 151, SmallData, -12), 142 (data_obj, 152, SmallData, 0), 143 (data_obj, 153, SmallData, None), 143 (data_obj, 150, SmallData, 12), 144 (data_obj, 151, SmallData, -12), 145 (data_obj, 152, SmallData, 0), 146 (data_obj, 153, SmallData, None), 144 147 (data_obj, 160, TextData, """This is a long piece of text. 145 148 It contains line breaks. … … 189 192 (fk_obj, 451, FKDataToField, "UAnchor 2"), 190 193 (fk_obj, 452, FKDataToField, None), 191 194 192 195 (data_obj, 500, Anchor, "Anchor 3"), 193 196 (data_obj, 501, Anchor, "Anchor 4"), … … 216 219 (pk_obj, 730, PositiveSmallIntegerPKData, 12), 217 220 (pk_obj, 740, SlugPKData, "this-is-a-slug"), 218 (pk_obj, 750, SmallPKData, 12), 219 (pk_obj, 751, SmallPKData, -12), 220 (pk_obj, 752, SmallPKData, 0), 221 (pk_obj, 750, SmallPKData, 12), 222 (pk_obj, 751, SmallPKData, -12), 223 (pk_obj, 752, SmallPKData, 0), 221 224 # (pk_obj, 760, TextPKData, """This is a long piece of text. 222 225 # It contains line breaks. … … 227 230 # (pk_obj, 790, XMLPKData, "<foo></foo>"), 228 231 ] 229 232 230 233 # Dynamically create serializer tests to ensure that all 231 234 # registered serializers are automatically tested. … … 235 238 def serializerTest(format, self): 236 239 # Clear the database first 237 management.flush(verbosity=0, interactive=False) 240 management.flush(verbosity=0, interactive=False) 238 241 239 242 # Create all the objects defined in the test data … … 246 249 transaction.leave_transaction_management() 247 250 248 # Add the generic tagged objects to the object list 251 # Add the generic tagged objects to the object list 249 252 objects.extend(Tag.objects.all()) 250 253 251 254 # Serialize the test database 252 255 serialized_data = serializers.serialize(format, objects, indent=2) 253 256 254 257 # Flush the database and recreate from the serialized data 255 management.flush(verbosity=0, interactive=False) 258 management.flush(verbosity=0, interactive=False) 256 259 transaction.enter_transaction_management() 257 260 transaction.managed(True) … … 261 264 transaction.leave_transaction_management() 262 265 263 # Assert that the deserialized data is the same 266 # Assert that the deserialized data is the same 264 267 # as the original source 265 268 for (func, pk, klass, datum) in test_data: 266 269 func[1](self, pk, klass, datum) 267 270 268 271 for format in serializers.get_serializer_formats(): 269 272 setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))
