Django

Code

Changeset 5248

Show
Ignore:
Timestamp:
05/15/07 11:14:55 (1 year ago)
Author:
mtredinnick
Message:

unicode: Made the serializers unicode-aware. Refs #3878, #4227.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/unicode/django/core/serializers/base.py

    r5081 r5248  
    88    from StringIO import StringIO 
    99from django.db import models 
     10from django.utils.encoding import smart_str, smart_unicode 
    1011 
    1112class SerializationError(Exception): 
     
    6061        else: 
    6162            value = field.flatten_data(follow=None, obj=obj).get(field.name, "") 
    62         return str(value) 
     63        return smart_unicode(value) 
    6364 
    6465    def start_serialization(self): 
     
    155156 
    156157    def __repr__(self): 
    157         return "<DeserializedObject: %s>" % str(self.object) 
     158        return "<DeserializedObject: %s>" % smart_str(self.object) 
    158159 
    159160    def save(self, save_m2m=True): 
  • django/branches/unicode/django/core/serializers/__init__.py

    r4712 r5248  
    77    >>> json = serializers.serialize("json", some_query_set) 
    88    >>> objects = list(serializers.deserialize("json", json)) 
    9          
     9 
    1010To add your own serializers, use the SERIALIZATION_MODULES setting:: 
    1111 
     
    3131    BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml" 
    3232except ImportError: 
    33     pass     
     33    pass 
    3434 
    3535_serializers = {} 
    36          
     36 
    3737def register_serializer(format, serializer_module): 
    3838    """Register a new serializer by passing in a module name.""" 
    3939    module = __import__(serializer_module, {}, {}, ['']) 
    4040    _serializers[format] = module 
    41      
     41 
    4242def unregister_serializer(format): 
    4343    """Unregister a given serializer""" 
    4444    del _serializers[format] 
    45      
     45 
    4646def get_serializer(format): 
    4747    if not _serializers: 
     
    5353        _load_serializers() 
    5454    return _serializers.keys() 
    55      
     55 
    5656def get_deserializer(format): 
    5757    if not _serializers: 
    5858        _load_serializers() 
    5959    return _serializers[format].Deserializer 
    60      
     60 
    6161def serialize(format, queryset, **options): 
    6262    """ 
  • django/branches/unicode/django/core/serializers/python.py

    r5241 r5248  
    88from django.core.serializers import base 
    99from django.db import models 
     10from django.utils.encoding import smart_unicode 
    1011 
    1112class Serializer(base.Serializer): 
     
    1314    Serializes a QuerySet to basic Python objects. 
    1415    """ 
    15      
     16 
    1617    def start_serialization(self): 
    1718        self._current = None 
    1819        self.objects = [] 
    19          
     20 
    2021    def end_serialization(self): 
    2122        pass 
    22          
     23 
    2324    def start_object(self, obj): 
    2425        self._current = {} 
    25          
     26 
    2627    def end_object(self, obj): 
    2728        self.objects.append({ 
    28             "model"  : str(obj._meta), 
    29             "pk"     : str(obj._get_pk_val()), 
     29            "model"  : smart_unicode(obj._meta), 
     30            "pk"     : smart_unicode(obj._get_pk_val()), 
    3031            "fields" : self._current 
    3132        }) 
    3233        self._current = None 
    33          
     34 
    3435    def handle_field(self, obj, field): 
    3536        self._current[field.name] = getattr(obj, field.name) 
    36          
     37 
    3738    def handle_fk_field(self, obj, field): 
    3839        related = getattr(obj, field.name) 
     
    4041            related = getattr(related, field.rel.field_name) 
    4142        self._current[field.name] = related 
    42      
     43 
    4344    def handle_m2m_field(self, obj, field): 
    4445        self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()] 
    45      
     46 
    4647    def getvalue(self): 
    4748        return self.objects 
     
    5051    """ 
    5152    Deserialize simple Python objects back into Django ORM instances. 
    52      
     53 
    5354    It's expected that you pass the Python objects themselves (instead of a 
    5455    stream or a string) to the constructor 
     
    6061        data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} 
    6162        m2m_data = {} 
    62          
     63 
    6364        # Handle each field 
    6465        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 
    6869            field = Model._meta.get_field(field_name) 
    69              
     70 
    7071            # Handle M2M relations 
    7172            if field.rel and isinstance(field.rel, models.ManyToManyRel): 
    72                 pks = [] 
    7373                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 
    8176            # Handle FK fields 
    8277            elif field.rel and isinstance(field.rel, models.ManyToOneRel): 
     
    8580                else: 
    8681                    data[field.attname] = None 
    87                      
     82 
    8883            # Handle all other fields 
    8984            else: 
    9085                data[field.name] = field.to_python(field_value) 
    91                  
     86 
    9287        yield base.DeserializedObject(Model(**data), m2m_data) 
    9388 
     
    10196        Model = None 
    10297    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) 
    10499    return Model 
  • django/branches/unicode/django/core/serializers/pyyaml.py

    r4734 r5248  
    2020    def end_serialization(self): 
    2121        yaml.dump(self.objects, self.stream, **self.options) 
    22          
     22 
    2323    def getvalue(self): 
    2424        return self.stream.getvalue() 
     
    3434    for obj in PythonDeserializer(yaml.load(stream)): 
    3535        yield obj 
    36          
     36 
  • django/branches/unicode/django/core/serializers/xml_serializer.py

    r5241 r5248  
    77from django.db import models 
    88from django.utils.xmlutils import SimplerXMLGenerator 
     9from django.utils.encoding import smart_unicode 
    910from xml.dom import pulldom 
    1011 
     
    1314    Serializes a QuerySet to XML. 
    1415    """ 
    15      
     16 
    1617    def indent(self, level): 
    1718        if self.options.get('indent', None) is not None: 
     
    2526        self.xml.startDocument() 
    2627        self.xml.startElement("django-objects", {"version" : "1.0"}) 
    27          
     28 
    2829    def end_serialization(self): 
    2930        """ 
     
    3334        self.xml.endElement("django-objects") 
    3435        self.xml.endDocument() 
    35          
     36 
    3637    def start_object(self, obj): 
    3738        """ 
     
    4041        if not hasattr(obj, "_meta"): 
    4142            raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) 
    42              
     43 
    4344        self.indent(1) 
    4445        self.xml.startElement("object", { 
    45             "pk"    : str(obj._get_pk_val()), 
    46             "model" : str(obj._meta), 
     46            "pk"    : smart_unicode(obj._get_pk_val()), 
     47            "model" : smart_unicode(obj._meta), 
    4748        }) 
    48          
     49 
    4950    def end_object(self, obj): 
    5051        """ 
     
    5354        self.indent(1) 
    5455        self.xml.endElement("object") 
    55          
     56 
    5657    def handle_field(self, obj, field): 
    5758        """ 
     
    6465            "type" : field.get_internal_type() 
    6566        }) 
    66          
     67 
    6768        # Get a "string version" of the object's data (this is handled by the 
    68         # serializer base class).  
     69        # serializer base class). 
    6970        if getattr(obj, field.name) is not None: 
    7071            value = self.get_string_value(obj, field) 
    71             self.xml.characters(str(value)) 
     72            self.xml.characters(smart_unicode(value)) 
    7273        else: 
    7374            self.xml.addQuickElement("None") 
    7475 
    7576        self.xml.endElement("field") 
    76          
     77 
    7778    def handle_fk_field(self, obj, field): 
    7879        """ 
     
    8384        related = getattr(obj, field.name) 
    8485        if related is not None: 
    85             self.xml.characters(str(getattr(related, field.rel.field_name))) 
     86            self.xml.characters(smart_unicode(getattr(related, field.rel.field_name))) 
    8687        else: 
    8788            self.xml.addQuickElement("None") 
    8889        self.xml.endElement("field") 
    89      
     90 
    9091    def handle_m2m_field(self, obj, field): 
    9192        """ 
     
    9697        self._start_relational_field(field) 
    9798        for relobj in getattr(obj, field.name).iterator(): 
    98             self.xml.addQuickElement("object", attrs={"pk" : str(relobj._get_pk_val())}) 
     99            self.xml.addQuickElement("object", attrs={"pk" : smart_unicode(relobj._get_pk_val())}) 
    99100        self.xml.endElement("field") 
    100          
     101 
    101102    def _start_relational_field(self, field): 
    102103        """ 
     
    107108            "name" : field.name, 
    108109            "rel"  : field.rel.__class__.__name__, 
    109             "to"   : str(field.rel.to._meta), 
     110            "to"   : smart_unicode(field.rel.to._meta), 
    110111        }) 
    111          
     112 
    112113class Deserializer(base.Deserializer): 
    113114    """ 
    114115    Deserialize XML. 
    115116    """ 
    116      
     117 
    117118    def __init__(self, stream_or_string, **options): 
    118119        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 
    122122    def next(self): 
    123123        for event, node in self.event_stream: 
     
    126126                return self._handle_object(node) 
    127127        raise StopIteration 
    128          
     128 
    129129    def _handle_object(self, node): 
    130130        """ 
    131131        Convert an <object> node to a DeserializedObject. 
    132132        """ 
    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. 
    134135        Model = self._get_model_from_node(node, "model") 
    135          
     136 
    136137        # Start building a data dictionary from the object.  If the node is 
    137138        # missing the pk attribute, bail. 
     
    141142 
    142143        data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)} 
    143          
     144 
    144145        # Also start building a dict of m2m data (this is saved as 
    145146        # {m2m_accessor_attribute : [list_of_related_objects]}) 
    146147        m2m_data = {} 
    147          
     148 
    148149        # Deseralize each field. 
    149150        for field_node in node.getElementsByTagName("field"): 
     
    153154            if not field_name: 
    154155                raise base.DeserializationError("<field> node is missing the 'name' attribute") 
    155              
     156 
    156157            # Get the field from the Model. This will raise a 
    157158            # FieldDoesNotExist if, well, the field doesn't exist, which will 
    158159            # be propagated correctly. 
    159160            field = Model._meta.get_field(field_name) 
    160              
     161 
    161162            # As is usually the case, relation fields get the special treatment. 
    162163            if field.rel and isinstance(field.rel, models.ManyToManyRel): 
     
    168169                    value = None 
    169170                else: 
    170                     value = field.to_python(getInnerText(field_node).strip().encode(self.encoding)
     171                    value = field.to_python(getInnerText(field_node).strip()
    171172                data[field.name] = value 
    172          
     173 
    173174        # Return a DeserializedObject so that the m2m data has a place to live. 
    174175        return base.DeserializedObject(Model(**data), m2m_data) 
    175          
     176 
    176177    def _handle_fk_field_node(self, node, field): 
    177178        """ 
     
    183184        else: 
    184185            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 
    187188    def _handle_m2m_field_node(self, node, field): 
    188189        """ 
    189         Handle a <field> node for a ManyToManyField 
     190        Handle a <field> node for a ManyToManyField. 
    190191        """ 
    191192        return [field.rel.to._meta.pk.to_python( 
    192                     c.getAttribute("pk").encode(self.encoding))  
     193                    c.getAttribute("pk")) 
    193194                    for c in node.getElementsByTagName("object")] 
    194      
     195 
    195196    def _get_model_from_node(self, node, attr): 
    196197        """ 
     
    212213                    (node.nodeName, model_identifier)) 
    213214        return Model 
    214          
    215      
     215 
     216 
    216217def getInnerText(node): 
    217218    """ 
     
    227228        else: 
    228229           pass 
    229     return "".join(inner_text) 
     230    return u"".join(inner_text) 
     231 
  • django/branches/unicode/tests/regressiontests/serializers_regress/tests.py

    r5241 r5248  
    33 
    44This class defines sample data and a dynamically generated 
    5 test case that is capable of testing the capabilities of  
     5test case that is capable of testing the capabilities of 
    66the serializers. This includes all valid data values, plus 
    77forward, backwards and self references. 
     
    2323    instance = klass(id=pk) 
    2424    instance.data = data 
    25     instance.save()     
     25    instance.save() 
    2626    return instance 
    2727 
     
    3333        instance.tags.create(data=tag) 
    3434    return instance 
    35      
     35 
    3636def fk_create(pk, klass, data): 
    3737    instance = klass(id=pk) 
     
    3939    instance.save() 
    4040    return instance 
    41      
     41 
    4242def m2m_create(pk, klass, data): 
    4343    instance = klass(id=pk) 
     
    6262def data_compare(testcase, pk, klass, data): 
    6363    instance = klass.objects.get(id=pk) 
    64     testcase.assertEqual(data, instance.data,  
     64    testcase.assertEqual(data, instance.data, 
    6565                         "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) 
    6666 
     
    6969    testcase.assertEqual(data[0], instance.data) 
    7070    testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()]) 
    71      
     71 
    7272def fk_compare(testcase, pk, klass, data): 
    7373    instance = klass.objects.get(id=pk) 
     
    8585    instance = klass.objects.get(data=data) 
    8686    testcase.assertEqual(data, instance.data) 
    87          
     87 
    8888# Define some data types. Each data type is 
    8989# actually a pair of functions; one to create 
     
    9797 
    9898test_data = [ 
    99     # Format: (data type, PK value, Model Class, data)   
     99    # Format: (data type, PK value, Model Class, data) 
    100100    (data_obj, 1, BooleanData, True), 
    101101    (data_obj, 2, BooleanData, False), 
     
    106106    (data_obj, 14, CharData, "NULL"), 
    107107    (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'), 
    108111    (data_obj, 20, DateData, datetime.date(2006,6,16)), 
    109112    (data_obj, 21, DateData, None), 
     
    138141    (data_obj, 140, SlugData, "this-is-a-slug"), 
    139142    (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), 
    144147    (data_obj, 160, TextData, """This is a long piece of text. 
    145148It contains line breaks. 
     
    189192    (fk_obj, 451, FKDataToField, "UAnchor 2"), 
    190193    (fk_obj, 452, FKDataToField, None), 
    191      
     194 
    192195    (data_obj, 500, Anchor, "Anchor 3"), 
    193196    (data_obj, 501, Anchor, "Anchor 4"), 
     
    216219    (pk_obj, 730, PositiveSmallIntegerPKData, 12), 
    217220    (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), 
    221224#     (pk_obj, 760, TextPKData, """This is a long piece of text. 
    222225# It contains line breaks. 
     
    227230#     (pk_obj, 790, XMLPKData, "<foo></foo>"), 
    228231] 
    229      
     232 
    230233# Dynamically create serializer tests to ensure that all 
    231234# registered serializers are automatically tested. 
     
    235238def serializerTest(format, self): 
    236239    # Clear the database first 
    237     management.flush(verbosity=0, interactive=False)     
     240    management.flush(verbosity=0, interactive=False) 
    238241 
    239242    # Create all the objects defined in the test data 
     
    246249    transaction.leave_transaction_management() 
    247250 
    248     # Add the generic tagged objects to the object list  
     251    # Add the generic tagged objects to the object list 
    249252    objects.extend(Tag.objects.all()) 
    250      
     253 
    251254    # Serialize the test database 
    252255    serialized_data = serializers.serialize(format, objects, indent=2) 
    253256 
    254257    # Flush the database and recreate from the serialized data 
    255     management.flush(verbosity=0, interactive=False)     
     258    management.flush(verbosity=0, interactive=False) 
    256259    transaction.enter_transaction_management() 
    257260    transaction.managed(True) 
     
    261264    transaction.leave_transaction_management() 
    262265 
    263     # Assert that the deserialized data is the same  
     266    # Assert that the deserialized data is the same 
    264267    # as the original source 
    265268    for (func, pk, klass, datum) in test_data: 
    266269        func[1](self, pk, klass, datum) 
    267      
     270 
    268271for format in serializers.get_serializer_formats(): 
    269272    setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))