2013-04-08 73 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響應。