Ticket #3661: serialize-attributes.2.patch

File serialize-attributes.2.patch, 7.5 KB (added by Øyvind Saltvik <oyvind.saltvik@…>, 8 years ago)

Serialize properties in own dict in python/ json, own tag in xml

  • django/core/serializers/json.py

     
    1616    Convert a queryset to JSON.
    1717    """
    1818    def end_serialization(self):
    19         simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **self.options)
     19        options = {}
     20        for option in self.options:
     21            if option in ['skipkeys', 'ensure_ascii', 'check_circular', 'allow_nan', 'cls', 'indent', 'encoding']:
     22                options[option] = self.options[option]
     23        simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **options)
    2024       
    2125    def getvalue(self):
    2226        return self.stream.getvalue()
  • django/core/serializers/xml_serializer.py

     
    8787        for relobj in getattr(obj, field.name).iterator():
    8888            self.xml.addQuickElement("object", attrs={"pk" : str(relobj._get_pk_val())})
    8989        self.xml.endElement("field")
    90        
     90
     91    def handle_property(self, obj, attr):
     92        """
     93        Called to handle a model property
     94        """
     95        self.xml.startElement("property", {
     96            "name" : attr
     97        })
     98
     99        # Get a "string version" of the object's data (this is handled by the
     100        # serializer base class).  None is handled specially.
     101        value = self.get_string_value(obj, attr)
     102        if value is not None:
     103            self.xml.characters(str(value))
     104
     105        self.xml.endElement("property")
     106
     107   
    91108    def _start_relational_field(self, field):
    92109        """
    93110        Helper to output the <field> element for relational fields
     
    208225            inner_text.extend(getInnerText(child))
    209226        else:
    210227           pass
    211     return "".join(inner_text)
    212  No newline at end of file
     228    return "".join(inner_text)
  • django/core/serializers/base.py

     
    2929
    3030        self.stream = options.get("stream", StringIO())
    3131        self.selected_fields = options.get("fields")
     32        self.serialize_attributes = options.get("attributes")
    3233
    3334        self.start_serialization()
    3435        for obj in queryset:
     
    4243                else:
    4344                    if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
    4445                        self.handle_fk_field(obj, field)
     46            if self.serialize_attributes:
     47                attrdict = obj.__class__.__dict__
     48                for attr in attrdict:
     49                    if isinstance(attrdict[attr], property):
     50                        self.handle_property(obj, attr)
    4551            for field in obj._meta.many_to_many:
    4652                if self.selected_fields is None or field.attname in self.selected_fields:
    4753                    self.handle_m2m_field(obj, field)
     
    6167                value = value.strftime("%Y-%m-%d %H:%M:%S")
    6268        elif isinstance(field, models.FileField):
    6369            value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
     70        elif isinstance(field, models.Field):
     71            value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
    6472        else:
    65             value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
     73            value = getattr(obj, field)
    6674        return str(value)
    6775
    6876    def start_serialization(self):
  • django/core/serializers/python.py

     
    2121        pass
    2222       
    2323    def start_object(self, obj):
    24         self._current = {}
     24        self._current = {'fields': {}, 'properties': {}}
    2525       
    2626    def end_object(self, obj):
    27         self.objects.append({
     27
     28        object = {
    2829            "model"  : str(obj._meta),
    2930            "pk"     : str(obj._get_pk_val()),
    30             "fields" : self._current
    31         })
     31            "fields" : self._current['fields']
     32        }
     33        if self._current['properties']:
     34            object.update({'properties':  self._current['properties']})
     35
     36        self.objects.append(object)
    3237        self._current = None
    3338       
    3439    def handle_field(self, obj, field):
    35         self._current[field.name] = getattr(obj, field.name)
     40        self._current['fields'][field.name] = getattr(obj, field.name)
    3641       
    3742    def handle_fk_field(self, obj, field):
    3843        related = getattr(obj, field.name)
    3944        if related is not None:
    4045            related = related._get_pk_val()
    41         self._current[field.name] = related
     46        self._current['fields'][field.name] = related
    4247   
    4348    def handle_m2m_field(self, obj, field):
    44         self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()]
    45    
     49        self._current['fields'][field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()]
     50
     51    def handle_property(self, obj, attr):
     52        self._current['properties'][attr] = getattr(obj, attr)
     53 
    4654    def getvalue(self):
    4755        return self.objects
    4856
  • tests/modeltests/serializers/models.py

     
    4040class AuthorProfile(models.Model):
    4141    author = models.OneToOneField(Author)
    4242    date_of_birth = models.DateField()
     43
     44    def is_cool(self):
     45        return True
     46    is_cool = property(is_cool)
    4347   
    4448    def __str__(self):
    4549        return "Profile of %s" % self.author
     
    130134# pk identifier.
    131135>>> profile = AuthorProfile(author=joe, date_of_birth=datetime(1970,1,1))
    132136>>> profile.save()
    133 
    134137>>> json = serializers.serialize("json", AuthorProfile.objects.all())
    135138>>> json
    136139'[{"pk": "1", "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
     
    139142...     print obj
    140143<DeserializedObject: Profile of Joe>
    141144
     145# Optionally serialize model properties using, attributes=True, this is also affected by the fields option
     146>>> xml = serializers.serialize("xml", AuthorProfile.objects.all(), attributes=True)
     147>>> xml
     148'<?xml version="1.0" encoding="utf-8"?>\\n<django-objects version="1.0"><object pk="1" model="serializers.authorprofile"><field type="DateField" name="date_of_birth">1970-01-01</field><property name="is_cool">True</property></object></django-objects>'
     149>>> json = serializers.serialize("json", AuthorProfile.objects.all(), attributes=True)
     150>>> json
     151'[{"pk": "1", "model": "serializers.authorprofile", "properties": {"is_cool": true}, "fields": {"date_of_birth": "1970-01-01"}}]'
     152
    142153# Objects ids can be referenced before they are defined in the serialization data
    143154# However, the deserialization process will need to be contained within a transaction
    144155>>> json = '[{"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": "4", "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": "4", "model": "serializers.author", "fields": {"name": "Agnes"}}]'
Back to Top