web-dev-qa-db-fra.com

Exporter le jeu de requêtes Django en JSON

Je veux sérialiser mon ensemble de requêtes et je le veux dans un format tel que cette vue affiche:

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 tout simplement pas comment sortir le queryset au lieu des données manuelles de l'exemple.

J'ai essayé

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

et

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

mais ça ne marchera pas. Qu'est-ce que je fais mal? Dois-je créer un encodeur JSON personnalisé?

26
user2232982

Vous pouvez utiliser JsonResponse avec values ​​ . Exemple simple:

from Django.http import JsonResponse

def some_view(request):
    data = list(SomeModel.objects.values())
    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, la réponse sera différente (sans retrait par défaut):

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

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

... et quelques notes pour de meilleures performances:

  • utilisez la pagination si votre requête est grande;
  • utilisez objects.values() pour spécifier la liste des champs obligatoires afin d'éviter la sérialisation et l'envoi au client des champs inutiles du modèle (vous pouvez également passer de fields à serializers.serialize);
36
Mark Mishyn

Cela n'a pas fonctionné, car les ensembles de requêtes ne sont pas sérialisables JSON.

1) Dans le cas de json.dumps, vous devez convertir explicitement votre 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) En cas de sérialiseurs. Les sérialiseurs acceptent l'objet sérialisable JSON ou QuerySet, mais un dictionnaire contenant un QuerySet ne l'est ni Essaye ça:

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

En savoir plus à ce sujet ici:

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

29
freakish

Pour une solution efficace, vous pouvez utiliser .values ​​() function pour obtenir une liste d'objets dict, puis l'envoyer 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 souhaité, transformez-le en réponse JSON comme ceci:

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

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

2
serfer2

Si l'objectif est de créer une API qui vous permet d'accéder à vos modèles au format JSON, je vous recommande d'utiliser le Django-restframework, un package extrêmement populaire au sein de la communauté Django pour réaliser ce type de tâches. 

Il inclut des fonctionnalités utiles telles que la pagination, la définition des 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 suggère néanmoins de créer une API appropriée à l'aide de Django Rest Framework au lieu de définir manuellement la réponse JSON.

1
Marcus Lind

Essaye ça:

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


    def get(self, request, *args, **kwargs):
        data = {}
        data["users"] = get_json_list(queryset)
        return JSONResponse(data)


def get_json_list(query_set):
    list_objects = []
    for obj in query_set:
        dict_obj = {}
        for field in obj._meta.get_fields():
            try:
                if field.many_to_many:
                    dict_obj[field.name] = get_json_list(getattr(obj, field.name).all())
                    continue
                dict_obj[field.name] = getattr(obj, field.name)
            except AttributeError:
                continue
        list_objects.append(dict_obj)
    return list_objects
0
k15