Django's serializer has some limitations which makes it a bit of a pain to use. Basically it will ignore any atributes that have been added to a model object.
The code below is for an alternative serializer. This version allows you select what attributes will be serialized on a per object basis. It also allows you to either serialize the data into json or xml.
The original json encoder was written by Wolfram Kriesing
Example Usage:
dumper = DataDumper()
dumper.selectObjectFields('class_name',[...fields...])
dumper.selectObjectFields('class_name',[...fields...])
dumper.dump(model_instance,'xml')
dumper.dump(model_instance,'json')
dumper.dump(queryset,'xml')
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import types
from django.db import models
import pyxslt.serialize
from django.utils import simplejson as json
from django.core.serializers.json import DateTimeAwareJSONEncoder
from decimal import *
class DataDumper:
fields = {}
def selectObjectFields(self,objectType,fields = []):
self.fields[objectType] = fields
def dump(self,data,format='xml'):
"""
The main issues with django's default json serializer is that properties that
had been added to a object dynamically are being ignored (and it also has
problems with some models).
"""
def _any(data):
ret = None
if type(data) is types.ListType:
ret = _list(data)
elif type(data) is types.DictType:
ret = _dict(data)
elif isinstance(data, Decimal):
# json.dumps() cant handle Decimal
ret = str(data)
elif isinstance(data, models.query.QuerySet):
# Actually its the same as a list ...
ret = _list(data)
elif isinstance(data, models.Model):
ret = _model(data)
else:
ret = data
return ret
def _model(data):
ret = {}
# If we only have a model, we only want to encode the fields.
objType = data.__class__.__name__
for f in data._meta.fields:
if (self.fields[objType]) and (f.attname in self.fields[objType]):
ret[f.attname] = _any(getattr(data, f.attname))
# And additionally encode arbitrary properties that had been added.
fields = dir(data.__class__) + ret.keys()
add_ons = [k for k in dir(data) if k not in fields]
for k in add_ons:
if (self.fields[objType]) and (k in self.fields[objType]):
ret[k] = _any(getattr(data, k))
return ret
def _list(data):
ret = []
for v in data:
ret.append(_any(v))
return ret
def _dict(data):
ret = {}
for k,v in data.items():
ret[k] = _any(v)
return ret
ret = _any(data)
if(format == 'xml'):
return pyxslt.serialize.toString(prettyPrintXml=False,data=ret,)
else:
return json.dumps(ret, cls=DateTimeAwareJSONEncoder)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 3 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
This was of great use, thanks! Now I have disposed my silly tiny json dumper function in favour of this more complete implementation.
#
Please login first before commenting.