Изведете 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 енкодер?


person user2232982    schedule 08.04.2013    source източник
comment
Какво не проработи? Прочетохте ли документите за сериализиране на набори от заявки? Предполагам, че проблемът е във връзките ForeignKey/M2M във вашия модел   -  person Timmy O'Mahony    schedule 08.04.2013


Отговори (7)


Можете да използвате JsonResponse с стойности. Прост пример:

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

Или друг подход с вградените сериализатори на 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')

В този случай резултатът е малко по-различен (без отстъп по подразбиране):

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

Трябва да кажа, че е добра практика да се използва нещо като marshmallow за сериализиране на набор от заявки.

...и няколко бележки за по-добро представяне:

  • използвайте пагинация, ако вашият набор от заявки е голям;
  • използвайте objects.values(), за да посочите списък със задължителни полета, за да избегнете сериализиране и изпращане на клиентски ненужни полета на модела (можете също да подадете fields до serializers.serialize);
person Mark Mishyn    schedule 15.06.2016
comment
Използването на JsonResponse с JSON е неправилно, вместо това трябва да се използва HttpResponse. Ако използвате - person Alex78191; 28.10.2017
comment
не харесвам формата на Django модел със специфични файлове {model: "name.sub", pk: 1, fields: {,…}}. Харесвам прост JSON със собствени полета. - person Alex78191; 28.10.2017
comment
@Alex78191 благодаря ти, прав си. Очаквах, че сериализаторите на Django работят по същия начин като DRF сериализаторите. - person Mark Mishyn; 29.10.2017
comment
съжалявам за ранда, но това е толкова сложно за връщане на много основни данни - person vladimir.gorea; 28.02.2019
comment
@vladimir.gorea има само 3-4 реда код + импортиране във всеки пример. - person Mark Mishyn; 28.02.2019
comment
@MarkMishyn Имах предвид сериализаторите на Django. Просто искам някаква променлива с прости json данни. Вероятно е по-лесно да се сериализирате. - person vladimir.gorea; 01.03.2019
comment
Вариант №1 от отговора на Марк Мишин е най-добрият вариант при използване на DRF. - person AwsAnurag; 31.10.2020
comment
@AwsAnurag, DRF има свои собствени сериализатори и клас Response, така че не е необходимо да използвате Json Response на Django или values_list. - person Mark Mishyn; 01.11.2020
comment
@Mark - Благодаря, да, но има определени ограничения при използване на персонализиран потребителски модел, където първата ви опция е по-бърз подход за връщане на GET отговор, без да се нарушават правилата на Django. Това, разбира се, е моето лично предпочитание и съм сигурен, че има по-добри начини. Гласувах за вашия отговор, защото съм сигурен, че това ще помогне на други, които не знаят за такива по-добри начини. благодаря отново :-) - person AwsAnurag; 01.11.2020
comment
Какво е SomeModel? - person Brian Wiley; 17.05.2021
comment
@BrianWiley това е екземпляр на django.db.Model - person Mark Mishyn; 17.05.2021

Не проработи, защото 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/

person freakish    schedule 08.04.2013
comment
Това е добър отговор. Ще отида с първото решение. Във второто ви решение как е възможно да присвоите „ключ“ на данните? Трябва ли да е нещо като {data: serializers.serialize(json, self.get_queryset())}? - person user2232982; 08.04.2013
comment
@user2232982 Не съм сигурен да бъда честен, винаги използвам първата техника. :) Вашето решение не е добро, защото получавате речник с JSON низ, така че все още трябва да го сериализирате, което води до двойно сериализиран обект. :О - person freakish; 08.04.2013
comment
Първата техника е изобретение на колелото. - person Alex78191; 28.10.2017

За ефективно решение можете да използвате .values() функция, за да получите списък с dict обекти и след това да го изхвърлите в json отговор, като използвате т.е. JsonResponse (не забравяйте да зададете safe=False).

След като имате желания обект от набор от заявки, трансформирайте го в JSON отговор по следния начин:

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

Можете да посочите имена на полета във функцията .values(), за да върнете само желани полета (примерът по-горе ще върне всички полета на модела в json обекти).

person serfer2    schedule 31.12.2018

За да върнете набора от заявки, който сте извлекли с queryset = Users.objects.all(),, първо трябва да ги сериализирате.

Сериализацията е процес на преобразуване на една структура от данни в друга. Използвайки изгледи, базирани на клас, можете да върнете JSON по този начин.

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)

Това ще изведе списък с JSON. За повече подробности как работи това вижте моята статия в блога Как за връщане на JSON отговор с Django. Влиза в повече подробности за това как бихте направили това.

person Royalbishop101    schedule 16.10.2020
comment
не вярвам, че това извежда JSON низ. Вярвам, че в крайна сметка получавате обект bytes, така че това не е много полезно решение, освен ако не искате да изпратите само JSON обратно на клиента. - person Jamie Marshall; 19.02.2021

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

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

person Marcus Lind    schedule 16.11.2017

Опитайте тази:

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
person k15    schedule 18.08.2016
comment
Раздаването на код и извършването на работа на други вместо тях, без да се обяснява първоначалният проблем и използваното решение, не помага много... - person matteeyah; 19.08.2016

from django.http import JsonResponse

def SomeFunction():
       dict1 = {}

       obj = list( Mymodel.objects.values() )

       dict1['data']=obj

return JsonResponse(dict1)

Опитайте този код за Django

person Sujith suji    schedule 03.12.2020