The DjangoJSONEncoder (scroll to the end of this module) provided by Django serializes dates in a specific format. I wanted to change this so that a date would be serialized as '2 days ago'.
A bit of Googling bought me to Jessy's very nice blog post, which explained very nicely how to create a custom Encoder to be used for serializing objects in Python. This seemed like a good idea, so I wrote my custom encoder to change the way dates are displayed;
SECONDS_IN_HR = 60 * 60
SECONDS_IN_MIN = 60
def default(self, object):
if isinstance(object, datetime.datetime):
delta = datetime.datetime.now() - object
return super(Web20DatesEncoder, self).default(object)
def get_delta_as_string(self, delta):
days = delta.days
seconds = delta.seconds
hours = 0
minutes = 0
hours = seconds / self.SECONDS_IN_HR
seconds = seconds % self.SECONDS_IN_HR
minutes = seconds / self.SECONDS_IN_MIN
seconds = seconds % self.SECONDS_IN_MIN
delta_str = ''
if days > 0:
delta_str += str(days) + ' days, '
if hours > 0:
delta_str += str(hours) + ' hours, '
if days <= 0 and seconds > 0:
delta_str += str(seconds) + ' secs, '
However, I could not figure out how to hook this class into the call chain so that it is used when my QuerySet is serialized as such;
res = serializers.serialize(”json”, questions)
One solution which came up was to use the 'cls' parameter in the call to serialize.
res = serializers.serialize(”json”, questions, cls=Web20DatesEncoder)
However, when I ran my code, there was an error:
dump() got multiple values for keyword argument ‘cls’
Why do we get this error? Maybe (I still do understand Python well enough to be sure) because, the end_serialization method in django.core.Serializers.json.Serializer has the following line:
simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
As you can see it specifically passes
simplejson.dump(...), and this is the reason why we get the above error message.
Now I do not know what is the right way to resolve this issue, but here's how I did it. I created a subclass of JSONSerializer, such that my subclass used my custom encoder.
from django.core.serializers.json import Serializer as JSONSerializer
simplejson.dump(self.objects, self.stream, cls=Web20DatesEncoder, **self.options)
and the client code which earlier instantiated JSONSerializer now uses DateModifyingJSONSerializer.
#Here is the code snippet which uses the above class
json_serializer = DateModifyingJSONSerializer()
res = json_serializer.serialize(query_set)
#instead of old code shown below
#res = json_serializer.serialize(query_set)
I hope you find this solution useful. Please leave a comment if it helped you, or if you know a better way to perform this task.