95

1 回の API 呼び出しで Django Rest Framework を使用して複数のインスタンスを保存および更新したいと考えています。たとえば、複数の「教師」を持つことができる「教室」モデルがあるとします。複数の教師を作成し、後ですべての教室番号を更新したい場合、どうすればよいですか? 教師ごとに API 呼び出しを行う必要がありますか?

現在、ネストされたモデルを保存できないことはわかっていますが、教師レベルで保存できるかどうか知りたいです。ありがとう!

4

9 に答える 9

88

これは少し前に尋ねられたことは知っていますが、自分でこれを理解しようとしているときに見つけました。

モデルのシリアライザー クラスをインスタンス化するときに渡すmany=Trueと、複数のオブジェクトを受け入れることができます。

これは、django rest framework docs でここに記載されています

私の場合、私のビューは次のようになりました。

class ThingViewSet(viewsets.ModelViewSet):
    """This view provides list, detail, create, retrieve, update
    and destroy actions for Things."""
    model = Thing
    serializer_class = ThingSerializer

シリアライザーと pass のインスタンス化を直接制御するためだけに大量のボイラープレートを書きたくなかったので、私のシリアライザー クラスでは代わりmany=Trueに をオーバーライドしました。__init__

class ThingSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        many = kwargs.pop('many', True)
        super(ThingSerializer, self).__init__(many=many, *args, **kwargs)

    class Meta:
        model = Thing
        fields = ('loads', 'of', 'fields', )

このビューのリスト URL に次の形式でデータを投稿します。

[
    {'loads':'foo','of':'bar','fields':'buzz'},
    {'loads':'fizz','of':'bazz','fields':'errrrm'}
]

これらの詳細を使用して 2 つのリソースを作成しました。それはよかったです。

于 2013-05-22T16:45:20.370 に答える
14

ディクショナリから配列に変換する request.DATA を取得することがよくわかりませんでした。これは、Tom Manterfield のソリューションを機能させる能力の制限でした。これが私の解決策です:

class ThingSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        many = kwargs.pop('many', True)
        super(ThingSerializer, self).__init__(many=many, *args, **kwargs)

    class Meta:
        model = Thing
        fields = ('loads', 'of', 'fields', )

class ThingViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet ):
    queryset = myModels\
        .Thing\
        .objects\
        .all()
    serializer_class = ThingSerializer

    def create(self, request, *args, **kwargs):
        self.user = request.user
        listOfThings = request.DATA['things']

        serializer = self.get_serializer(data=listOfThings, files=request.FILES, many=True)
        if serializer.is_valid():
            serializer.save()
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED,
                            headers=headers)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

そして、これと同等のものをクライアントで実行します。

var things = {    
    "things":[
        {'loads':'foo','of':'bar','fields':'buzz'},
        {'loads':'fizz','of':'bazz','fields':'errrrm'}]
}
thingClientResource.post(things)
于 2014-03-06T22:12:39.883 に答える
13

フレームワークの提案されたアーキテクチャを尊重する最善の方法は、次のような mixin を作成することだと思います。

class CreateListModelMixin(object):

    def create(self, request, *args, **kwargs):
        """
            Create a list of model instances if a list is provided or a
            single model instance otherwise.
        """
        data = request.data
        if isinstance(data, list):
            serializer = self.get_serializer(data=request.data, many=True)
        else:
            serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED,
                    headers=headers)

次に、次のように ModelViewSet の CreateModelMixin をオーバーライドできます。

class <MyModel>ViewSet(CreateListModelMixin, viewsets.ModelViewSet):
    ...
    ...

クライアントでは、次のように作業できます。

var things = [    
    {'loads':'foo','of':'bar','fields':'buzz'},
    {'loads':'fizz','of':'bazz','fields':'errrrm'}
]
thingClientResource.post(things)

また

var thing = {
    'loads':'foo','of':'bar','fields':'buzz'
}
    
thingClientResource.post(thing)

編集:

ロジャー・コリンズが彼の応答で示唆しているように、「作成」よりも get_serializer メソッドを上書きする方が賢明です。

于 2016-10-08T15:31:22.593 に答える
4

Django REST Frameworkのドキュメントのジェネリックビュー」ページには、ListCreateAPIViewジェネリックビューは「モデルインスタンスのコレクションを表すための読み取り/書き込みエンドポイントに使用される」と記載されています。

それが私が探し始めるところです(そして、私たちのプロジェクトでもこの機能がすぐに必要になるので、実際に見ていきます)。

GenericViewsページのではたまたまを使用していることにも注意してくださいListCreateAPIView

于 2013-02-11T14:30:58.457 に答える