Вывод Django-запроса как JSON - программирование
Подтвердить что ты не робот

Вывод Django-запроса как JSON

Я хочу сериализовать свой запрос, и я хочу его в формате, когда это представление выводит:

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')

Я просто не знаю, как вывести набор запросов вместо ручных данных в примере.

Я пробовал

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

и

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

но он не будет работать. Что я делаю не так? Нужно ли создавать пользовательский JSON Encoder?

4b9b3361

Ответ 1

Это не сработало, потому что QuerySets не являются сериализуемыми JSON.

1) В случае json.dumps вам необходимо явно преобразовать ваш QuerySet в сериализуемые объекты JSON:

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

И сериализация:

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

2) В случае сериализаторов. Сериализаторы принимают либо сериализуемый объект JSON, либо QuerySet, но словарь, содержащий QuerySet, не является ни тем, ни другим. Попробуйте следующее:

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

Подробнее об этом читайте здесь:

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

Ответ 2

Простой пример:

from django.http import JsonResponse

def some_view(request):
    data = list(SomeModel.objects.values())
    return JsonResponse(data, safe=False)  # or JsonResponse({'data': data})

Или другой подход:

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')

В этом случае ответ будет бит другим (без отступа по умолчанию):

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

Я должен сказать, что хорошая практика использовать что-то вроде marshmallow для сериализации объектов.

И есть несколько заметок, как сделать ваше представление как можно быстрее для лучшей производительности:

  • используйте разбиение на страницы, если ваш запрос очень большой;
  • используйте objects.values(), чтобы указать список обязательных полей, чтобы избежать сериализации и отправки ненужным полям модели клиента (вы также можете передать fields в serializers.serialize);
  • установите подходящий settings.CONN_MAX_AGE, например 500 (значение из документации heroku);
  • вы можете использовать функцию, основанную на представлении, для лучшей производительности (но четкий код, очевидно, лучше, чем чуть более быстрый код, будьте осторожны);

Ответ 3

Попробуйте следующее:

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

Ответ 4

Если целью является создание API, который позволит вам получить доступ к вашим моделям в формате JSON, я рекомендую вам использовать django-restframework, который является чрезвычайно популярным пакетом в сообществе Django для достижения таких задач.

Он включает полезные функции, такие как разбиение на страницы, определение сериализаторов, вложенные модели/отношения и многое другое. Даже если вы хотите выполнять незначительные задачи Javascript и Ajax-вызовы, я бы по-прежнему предлагал вам создать правильный API с помощью Django Rest Framework вместо того, чтобы вручную определять ответ JSON.