2013-04-08 74 views
15

我想序列我的查询集,我想它的格式为这种观点输出:输出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编码器?

+0

什么没有工作?你有没有读过[序列化查询集的文档](https://docs.djangoproject.com/en/dev/topics/serialization/)?我可以想象这个问题与您的模型中的ForeignKey/M2M关系 – 2013-04-08 08:16:55

回答

24

它没有用,因为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/

+0

这是一个很好的答案。我将采用第一种解决方案。在第二种解决方案中,如何为数据分配“密钥”? 它应该像{“data”:serializers.serialize(“json”,self.get_queryset())}? – user2232982 2013-04-08 09:35:37

+1

@ user2232982我不确定是否诚实,我总是使用第一种技术。 :)你的解决方案不好,因为你得到一个带有JSON字符串的字典,所以你仍然需要序列化它,产生双重序列化的对象。 :O – freakish 2013-04-08 09:37:48

+0

第一个技巧是车轮的发明。 – Alex78191 2017-10-28 19:50:25

13

简单的例子:

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()指定所需字段的列表以避免序列化并向客户端发送不必要的模型字段(您也可以通过fieldsserializers.serialize);
  • 设置合适settings.CONN_MAX_AGE,例如500(来自heroku文档的价值);
  • 你可以使用基于函数的视图来获得更好的性能(但明显的代码显然比稍快的代码更好,要小心);
+0

对JSON使用'JsonResponse'不正确,应该使用'HttpResponse'。如果使用 – Alex78191 2017-10-28 19:20:52

+0

我不喜欢带特定文件的Django模型格式'{model:“name.sub”,pk:1,fields:{,...}}'。我喜欢[简单的JSON和它自己的字段](https://stackoverflow.com/a/30243413/4854931)。 – Alex78191 2017-10-28 19:59:02

+0

@ Alex78191谢谢你,你是对的。我预计Django的序列化器与DRF序列化器的工作方式相同。 – 2017-10-29 06:49:00

0

试试这个:

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

给出代码并为他人做好工作,而不用解释原始问题和所用的解决方案,并没有多大帮助...... – matteeyah 2016-08-18 21:28:07

0

如果目标是建立一个API,它允许您访问您的模型JSON格式的,我建议你使用django-restframework是Django的内颇受欢迎的包社区来实现这种类型的任务。

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