Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing objects containing django querysets

Django provides tools to serialize querysets (django.core.serializers), but what about serializing querysets living inside other objects (like dictionaries)?

I want to serialize the following dictionary:

dictionary = { 'alfa': queryset1, 'beta': queryset2, } 

I decided to do this using simplejson (comes with django). I extended simplejson.JSONEncoder the following way:

from django.utils import simplejson
from django.core import serializers

class HandleQuerySets(simplejson.JSONEncoder):
     """ simplejson.JSONEncoder extension: handle querysets """
     def default(self, obj):
         if isinstance(obj, QuerySet):
             return serializers.serialize("json", obj, ensure_ascii=False)

         return simplejson.JSONEncoder.default(self, obj)

Then I do: simplejson.dumps( dictionary, cls=HandleQuerySets), but the returned dicionary looks like this:

{ "alfa": "[{\"pk\": 1, \"model\": \"someapp.somemodel\", \"fields\": {\"name\": \"alfa\"}}]",
  "beta": "[{\"pk\": 1, \"model\": \"someapp.somemodel\", \"fields\": {\"name\": \"alfa\"}}]" }

Django-generated JSON is inserted to the dictionary as string, not JSON. What am I doing wrong?

like image 715
Pawel Furmaniak Avatar asked Jan 19 '10 13:01

Pawel Furmaniak


1 Answers

The correct way to do this would be:

from django.utils import simplejson
from django.core import serializers
from django.db.models.query import QuerySet

class HandleQuerySets(simplejson.JSONEncoder):
     """ simplejson.JSONEncoder extension: handle querysets """
     def default(self, obj):
         if isinstance(obj, QuerySet):
             return serializers.serialize("python", obj, ensure_ascii=False)
         return simplejson.JSONEncoder.default(self, obj)

Because serializers.serialize("json", [...]) returns a string ; if you ask for the python serializer, you get a dictionnary, and json encodes whatever is returned by your encoder's default method. Look at the json documentation for details.

You will have to handle more types in your encoder class (such as datetime objects), but you get the idea.

like image 107
Luper Rouch Avatar answered Sep 28 '22 04:09

Luper Rouch