web-dev-qa-db-fra.com

Sérialisation JSON Django Modèles avec simplejson

J'aimerais utiliser simplejson pour sérialiser un Django modèle. Le sérialiseur de Django ne prend pas en charge les dictionnaires ... et simplejson ne prend pas en charge Django Querysets. C'est une énigme.

Dans le modèle, il y a des sponsors qui ont une clé étrangère au niveau de sponsor, j'essaie de regrouper tous les sponsors qui appartiennent à un certain niveau de sponsor. Voici le code qui génère la liste:

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]

Voici ce que sponsor_dict ressemble une fois qu'il est "fait"

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

Je n'ai ajouté qu'un seul sponsor dans chaque niveau, à l'exception du bronze, juste pour montrer comment cela fonctionne. Tout ce que je veux faire, c'est mettre tout "dans JSON" pour que jQuery puisse l'interpréter facilement. Les autres sérialiseurs de Django (comme XML ou YAML) peuvent-ils accomplir cela? Puis-je "étendre" le Django JSON Serializer pour gérer les dictionnaires ou "étendre" simplejson pour gérer Django les objets QuerySet?

33
Zack

J'irais avec l'extension simplejson . Fondamentalement, vous souhaitez brancher la sérialisation de Django lorsque l'encodeur JSON rencontre un QuerySet. Vous pouvez utiliser quelque chose comme:

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)

Pour plus d'informations sur la méthode default, consultez documentation simplejson . Mettez cela dans un module python, puis importez dumps et vous êtes prêt à partir. Mais notez que cette fonction ne vous aidera qu'à sérialiser les instances de QuerySet, pas Model directement.

39
Clément

Un moyen vraiment flexible de sérialiser la plupart des structures dans Django est d'utiliser la classe sérialiseur trouvée ici

13
selaux

sur la base de la réponse de Clement, je l'ai fait pour obtenir également des modèles dans JSON.

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
10
jcage