web-dev-qa-db-ja.com

出力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エンコーダーを作成する必要がありますか?

35
user2232982

JsonResponsevalues を併用できます。簡単な例:

_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_に渡すこともできます)。
49
Mark Mishyn

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/

31
freakish

効率的な解決策として、 。values() 関数を使用してdictオブジェクトのリストを取得し、ie JsonResponse を使用してjson応答にダンプできます(_safe=False_)。

目的のクエリセットオブジェクトを取得したら、次のようにJSON応答に変換します。

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

.values() functionでフィールド名を指定して、必要なフィールドのみを返すことができます(上記の例では、jsonオブジェクトのすべてのモデルフィールドが返されます)。

4
serfer2

JSON形式でモデルにアクセスできるAPIを構築することが目標の場合は、Django-restframeworkこれは、このタイプのタスクを達成するためのDjangoコミュニティ内で非常に人気のあるパッケージです。

ページネーション、シリアライザの定義、ネストされたモデル/関係などの便利な機能が含まれています。マイナーなJavascriptタスクとAjax呼び出しのみを行いたい場合でも、JSON応答を手動で定義する代わりにDjango Rest Frameworkを使用して適切なAPIを構築することをお勧めします。

1
Marcus Lind

これを試して:

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
k15