89 votes

Sortie du jeu de requêtes Django en JSON

Je veux sérialiser mon queryset, et je le veux dans un format tel que cette vue le produit :

class JSONListView(ListView):
    queryset = Users.objects.all()

    def get(self, request, *args, **kwargs):
        return HttpResponse(json.dumps({'data': [['bar','foo','bar','foo'],['foo','bar','foo','bar']]}, indent=4), content_type='application/json')

Je ne sais simplement pas comment sortir le queryset au lieu des données manuelles dans l'exemple.

J'ai essayé

json.dumps({"data": self.get_queryset()})

et

serializers.serialize("json", {'data': self.get_queryset()})

mais ça ne marche pas. Que dois-je faire de mal ? Dois-je créer un encodeur JSON personnalisé ?

148voto

Mark Mishyn Points 912

Vous pouvez utiliser JsonResponse con valores . Un exemple simple :

from django.http import JsonResponse

def some_view(request):
    data = list(SomeModel.objects.values())  # wrap in list(), because QuerySet is not JSON serializable
    return JsonResponse(data, safe=False)  # or JsonResponse({'data': data})

Ou une autre approche avec Les sérialiseurs intégrés de Django :

from django.core import serializers
from django.http import HttpResponse

def some_view(request):
    qs = SomeModel.objects.all()
    qs_json = serializers.serialize('json', qs)
    return HttpResponse(qs_json, content_type='application/json')

Dans ce cas, le résultat est légèrement différent (sans indentation par défaut) :

[
    {
        "model": "some_app.some_model",
        "pk": 1,
        "fields": {
            "name": "Elon",
            "age": 48,
            ...
        }
    },
    ...
]

Je dois dire que c'est une bonne pratique d'utiliser quelque chose comme guimauve pour sérialiser le queryset.

...et quelques notes pour une meilleure performance :

  • utilisez la pagination si votre jeu de questions est important ;
  • utiliser objects.values() pour spécifier la liste des champs obligatoires afin d'éviter la sérialisation et l'envoi au client de champs inutiles du modèle (vous pouvez également passer le paramètre fields a serializers.serialize ) ;

43voto

freakish Points 20067

Cela n'a pas fonctionné, car les QuerySets ne sont pas sérialisables JSON.

1) En cas de json.dumps vous devez explicitement convertir vos QuerySet en objets sérialisables JSON :

class Model(model.Model):
    def as_dict(self):
        return {
            "id": self.id,
            # other stuff
        }

Et la sérialisation :

dictionaries = [ obj.as_dict() for obj in self.get_queryset() ]
return HttpResponse(json.dumps({"data": dictionaries}), content_type='application/json')

2) Dans le cas des sérialiseurs. Les sérialiseurs acceptent soit un objet sérialisable JSON soit un QuerySet, mais un dictionnaire contenant un QuerySet n'est ni l'un ni l'autre. Essayez ceci :

serializers.serialize("json", self.get_queryset())

Pour en savoir plus, cliquez ici :

https://docs.djangoproject.com/en/dev/topics/serialization/

21voto

serfer2 Points 359

Pour une solution efficace, vous pouvez utiliser .values() pour obtenir une liste d'objets dict et ensuite la vider dans une réponse json en utilisant i.e. JsonResponse (n'oubliez pas de définir safe=False ).

Une fois que vous avez votre objet queryset désiré, transformez-le en réponse JSON comme ceci :

...
data = list(queryset.values())
return JsonResponse(data, safe=False)

Vous pouvez spécifier les noms des champs dans .values() afin de ne renvoyer que les champs souhaités (l'exemple ci-dessus renvoie tous les champs du modèle dans des objets json).

8voto

Royalbishop101 Points 149

Pour retourner le queryset que vous avez récupéré avec queryset = Users.objects.all(), vous devez d'abord les sérialiser.

La sérialisation est le processus de conversion d'une structure de données en une autre. En utilisant les vues basées sur les classes, vous pourriez retourner du JSON comme ceci.

from django.core.serializers import serialize
from django.http import JsonResponse
from django.views.generic import View

class JSONListView(View):
    def get(self, request, *args, **kwargs):
        qs = User.objects.all()
        data = serialize("json", qs)
        return JsonResponse(data)

Cela produira une liste de JSON. Pour plus de détails sur ce fonctionnement, consultez mon article de blog. Comment renvoyer une réponse JSON avec Django ? . Il explique plus en détail comment s'y prendre.

5voto

Marcus Lind Points 3111

Si le but est de construire une API qui vous permette d'accéder à vos modèles au format JSON, je vous recommande d'utiliser la fonction django-restframework qui est un paquet extrêmement populaire au sein de la communauté Django pour réaliser ce type de tâches.

Il comprend des fonctionnalités utiles telles que la pagination, la définition de sérialiseurs, les modèles/relations imbriqués, etc. Même si vous ne souhaitez effectuer que des tâches Javascript mineures et des appels Ajax, je vous conseille de construire une API appropriée à l'aide du cadre Django Rest au lieu de définir manuellement la réponse JSON.

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