Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Serializing Django Models with simplejson

I'd like to use simplejson to serialize a Django model. Django's serializer doesn't support dictionaries... and simplejson doesn't support Django Querysets. This is quite a conundrum.

In the model there's sponsors that have a Foreign Key to sponsor level, I'm trying to group all the sponsors that belong to a certain sponsor level together. Here's the code that generates the list:

from django.shortcuts import get_list_or_404
from special_event.models import Sponsor, SponsorLevel

sponsor_dict = {}

roadie_sponsors = get_list_or_404(Sponsor, level__category = SponsorLevel.ROADIE_CHOICE)

for item in roadie_sponsors:
    try:
        sponsor_dict[item.level.name].append(item)
    except KeyError:
        sponsor_dict[item.level.name] = [item]

Here's what sponsor_dict looks like once it's "made"

{
    'Fan': [<Sponsor: Fan Sponsor>], 
    'VIP': [<Sponsor: VIP Sponsor>],
    'Groupie': [<Sponsor: Groupie Sponsor>],
    'Silver': [<Sponsor: Silver Sponsor>],
    'Bronze': [<Sponsor: Another Bronze Sponsor>, <Sponsor: Bronze Sponsor>]
}

I only added one sponsor in each level, except for bronze, just to show how it works. All I want to do is get it "all" into JSON so jQuery can interpret it easily. Can Django's other serializers (like XML or YAML) accomplish this? Can I "extend" the Django JSON Serializer to handle dictionaries or "extend" simplejson to handle Django QuerySet objects?

like image 428
Zack Avatar asked Feb 12 '10 05:02

Zack


3 Answers

I would go with extending simplejson. Basically, you want to plug in django's serialization when the JSON encoder encounters a QuerySet. You could use something like:

from json import dumps, loads, JSONEncoder

from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.utils.functional import curry

class DjangoJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, QuerySet):
            # `default` must return a python serializable
            # structure, the easiest way is to load the JSON
            # string produced by `serialize` and return it
            return loads(serialize('json', obj))
        return JSONEncoder.default(self,obj)

# partial function, we can now use dumps(my_dict) instead
# of dumps(my_dict, cls=DjangoJSONEncoder)
dumps = curry(dumps, cls=DjangoJSONEncoder)

For more info on default method, have a look at simplejson documentation. Put that in a python module, then import dumps and you're good to go. But note that this function will only help you serializing QuerySet instances, not Model instances directly.

like image 130
Clément Avatar answered Oct 12 '22 19:10

Clément


A really flexible way to serialize most structures in django is to use the serializer class found here

like image 42
selaux Avatar answered Oct 12 '22 20:10

selaux


based on Clement's answer, I did this to get models into JSON as well.

def toJSON(obj):
   if isinstance(obj, QuerySet):
       return simplejson.dumps(obj, cls=DjangoJSONEncoder)
   if isinstance(obj, models.Model):
       #do the same as above by making it a queryset first
       set_obj = [obj]
       set_str = simplejson.dumps(simplejson.loads(serialize('json', set_obj)))
       #eliminate brackets in the beginning and the end 
       str_obj = set_str[1:len(set_str)-2]
   return str_obj
like image 10
jcage Avatar answered Oct 12 '22 20:10

jcage