33 votes

Sérialisation JSON des modèles Django avec simplejson

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

Dans le modèle, il y a des sponsors qui ont une clé étrangère pour le niveau du 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 on dirait qu'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, sauf pour le bronze, juste pour montrer comment cela fonctionne. Tout ce que je veux faire, c'est convertir le tout en 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 sérialiseur Django JSON pour gérer les dictionnaires ou " étendre " simplejson pour gérer les objets Django QuerySet ?

39voto

Clément Points 4224

Je choisirais l'extension simplejson . En gros, vous voulez intégrer la sérialisation de Django lorsque l'encodeur JSON rencontre un QuerySet. Vous pourriez 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 default consultez le site 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 QuerySet les instances, et non Model directement les instances.

13voto

selaux Points 129

Une manière vraiment flexible de sérialiser la plupart des structures dans django est d'utiliser la classe serializer trouvée ici

10voto

jcage Points 456

En me basant sur la réponse de Clement, j'ai également procédé de la sorte pour convertir les modèles en 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X