【问题标题】:Output Django queryset as JSON将 Django 查询集输出为 JSON
【发布时间】:2013-03-30 05:56:36
【问题描述】:

我想序列化我的查询集,并且我希望它采用此视图输出的格式:

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 编码器吗?

【问题讨论】:

标签: django json listview


【解决方案1】:

您可以将JsonResponsevalues 一起使用。简单例子:

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's built-in serializers的另一种方法:

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

【讨论】:

  • 使用 JsonResponse 和 JSON 是不正确的,应该使用 HttpResponse 代替。如果使用
  • 我不喜欢带有特定文件 {model: "name.sub", pk: 1, fields: {,…}} 的 Django 模型格式。我喜欢simple JSON with it's own fields
  • @Alex78191 谢谢你,你是对的。我希望 Django 的序列化程序与 DRF 序列化程序的工作方式相同。
  • 对不起,这对于返回非常基本的数据来说太复杂了
  • @vladimir.gorea 每个示例中只有 3-4 行代码 + 导入。
【解决方案2】:

它不起作用,因为 QuerySet 不是 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/

【讨论】:

  • 这是一个很好的答案。我将采用第一个解决方案。在您的第二个解决方案中,如何为数据分配“密钥”?应该是 {"data": serializers.serialize("json", self.get_queryset())} 之类的吗?
  • @user2232982 我不确定说实话,我总是使用第一种技术。 :) 你的解决方案不好,因为你得到了一个带有 JSON 字符串的字典,所以你仍然需要对其进行序列化,从而导致双重序列化对象。 :O
  • 第一个技术是轮子的发明。
【解决方案3】:

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

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

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

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

【讨论】:

    【解决方案4】:

    要返回您使用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 列表。有关其工作原理的更多详细信息,请查看我的博客文章 How to return a JSON Response with Django。它更详细地说明了您将如何处理。

    【讨论】:

    • 我不相信这会输出 JSON 字符串。我相信你最终会得到一个字节对象,所以这不是一个非常有用的解决方案,除非你打算只将 JSON 发送回客户端。
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

      另一种将查询集转换为 JSON 的方法是将必要的元素附加到带有循环的空列表中。它提供设计可定制的 JSON。

      queryset = Users.objects.all()
      output = []
      for query in queryset:
         output.append('id': query.id, 'name': query.name, etc...)
      return JSONResponse(output, safe=False) 
      

      【讨论】:

        【解决方案7】:

        试试这个:

        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
        

        【讨论】:

        • 提供代码并为他们做其他工作,而不解释原始问题和使用的解决方案,并没有多大帮助......
        【解决方案8】:
        from django.http import JsonResponse
        
        def SomeFunction():
               dict1 = {}
        
               obj = list( Mymodel.objects.values() )
        
               dict1['data']=obj
        
        return JsonResponse(dict1)
        

        在 Django 中试试这个代码

        【讨论】:

          猜你喜欢
          • 2011-07-05
          • 2017-01-23
          • 1970-01-01
          • 2018-07-31
          • 1970-01-01
          • 2012-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多