クエリセットをシリアル化し、このビューが出力する形式にしたい:
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エンコーダーを作成する必要がありますか?
JsonResponse と values を併用できます。簡単な例:
_from Django.http import JsonResponse
def some_view(request):
data = list(SomeModel.objects.values())
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": "Ivan",
"age": 35,
...
}
},
...
]
_
Marshmallow のようなものを使用してクエリセットをシリアル化することをお勧めします。
...およびパフォーマンス向上のための注意事項:
objects.values()
を使用して必要なフィールドのリストを指定し、シリアル化およびクライアントへの不必要なモデルのフィールドの送信を回避します(fields
を_serializers.serialize
_に渡すこともできます)。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())
詳細についてはこちらをご覧ください。
効率的な解決策として、 。values() 関数を使用してdictオブジェクトのリストを取得し、ie JsonResponse を使用してjson応答にダンプできます(_safe=False
_)。
目的のクエリセットオブジェクトを取得したら、次のようにJSON応答に変換します。
_...
data = list(queryset.values())
return JsonResponse(data, safe=False)
_
.values()
functionでフィールド名を指定して、必要なフィールドのみを返すことができます(上記の例では、jsonオブジェクトのすべてのモデルフィールドが返されます)。
JSON形式でモデルにアクセスできるAPIを構築することが目標の場合は、Django-restframework
これは、このタイプのタスクを達成するためのDjangoコミュニティ内で非常に人気のあるパッケージです。
ページネーション、シリアライザの定義、ネストされたモデル/関係などの便利な機能が含まれています。マイナーなJavascriptタスクとAjax呼び出しのみを行いたい場合でも、JSON応答を手動で定義する代わりにDjango Rest Frameworkを使用して適切なAPIを構築することをお勧めします。
これを試して:
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