将Django queryset输出为JSON

use*_*982 38 django json listview

我想序列化我的查询集,我希望它以这种视图输出的格式:

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')
Run Code Online (Sandbox Code Playgroud)

我根本不知道如何输出查询集而不是示例中的手动数据.

我试过了

json.dumps({"data": self.get_queryset()})
Run Code Online (Sandbox Code Playgroud)

serializers.serialize("json", {'data': self.get_queryset()})
Run Code Online (Sandbox Code Playgroud)

但它不会工作.我究竟做错了什么?我是否需要制作自定义JSON编码器?

Mar*_*hyn 55

您可以将JsonResponse一起使用.简单的例子:

from django.http import JsonResponse

def some_view(request):
    data = list(SomeModel.objects.values())  # use list(), because QuerySet is not JSON serializable
    return JsonResponse(data, safe=False)  # or JsonResponse({'data': data})
Run Code Online (Sandbox Code Playgroud)

或者使用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')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,响应将有点不同(默认情况下没有缩进):

[
    {
        "model": "some_app.some_model",
        "pk": 1,
        "fields": {
            "name": "Ivan",
            "age": 35,
            ...
        }
    },
    ...
]
Run Code Online (Sandbox Code Playgroud)

我必须说,使用像marshmallow这样的东西来序列化查询集是一种好习惯.

......以及一些表现更好的笔记:

  • 如果你的查询集很大,请使用分页;
  • 用于objects.values()指定必填字段列表以避免序列化并向客户端发送不必要的模型字段(您也可以传递fieldsserializers.serialize);

  • 我不喜欢带有特定字段 `{model: "name.sub", pk: 1, fields: {,…}}` 的 Django 模型格式。我喜欢[带有自己的字段的简单 JSON](/sf/answers/2117038941/)。 (2认同)
  • 很抱歉兰特,但这对于返回非常基本的数据来说太复杂了 (2认同)

fre*_*ish 31

它不起作用,因为QuerySets不是JSON可序列化的.

1)如果json.dumps您必须明确地将QuerySet转换为JSON可序列化对象:

class Model(model.Model):
    def as_dict(self):
        return {
            "id": self.id,
            # other stuff
        }
Run Code Online (Sandbox Code Playgroud)

和序列化:

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

2)在序列化器的情况下.序列化程序接受JSON可序列化对象或QuerySet,但是包含QuerySet的字典既不是.试试这个:

serializers.serialize("json", self.get_queryset())
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多相关信息:

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


Roy*_*101 7

要返回您检索的查询集,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)
Run Code Online (Sandbox Code Playgroud)

这将输出一个 JSON 列表。有关其工作原理的更多详细信息,请查看我的博客文章How to return a JSON Response with Django。它更详细地介绍了您将如何进行此操作。


Mar*_*ind 5

如果目标是构建一个允许您以 JSON 格式访问模型的 API,我建议您使用django-restframeworkDjango 社区中非常流行的包来完成此类任务。

它包括有用的功能,例如分页、定义序列化程序、嵌套模型/关系等。即使您只想执行次要的 Javascript 任务和 Ajax 调用,我仍然建议您使用 Django Rest Framework 构建适当的 API,而不是手动定义 JSON 响应。


ser*_*er2 5

为了获得有效的解决方案,您可以使用.values()函数获取dict对象的列表,然后使用ie JsonResponse(记住要设置safe=False)将其转储到json响应中。

获得所需的queryset对象后,将其转换为JSON响应,如下所示:

...
data = list(queryset.values())
return JsonResponse(data, safe=False)
Run Code Online (Sandbox Code Playgroud)

您可以在.values()函数中指定字段名称,以便仅返回所需的字段(上面的示例将返回json对象中的所有模型字段)。