1 回の API 呼び出しで Django Rest Framework を使用して複数のインスタンスを保存および更新したいと考えています。たとえば、複数の「教師」を持つことができる「教室」モデルがあるとします。複数の教師を作成し、後ですべての教室番号を更新したい場合、どうすればよいですか? 教師ごとに API 呼び出しを行う必要がありますか?
現在、ネストされたモデルを保存できないことはわかっていますが、教師レベルで保存できるかどうか知りたいです。ありがとう!
1 回の API 呼び出しで Django Rest Framework を使用して複数のインスタンスを保存および更新したいと考えています。たとえば、複数の「教師」を持つことができる「教室」モデルがあるとします。複数の教師を作成し、後ですべての教室番号を更新したい場合、どうすればよいですか? 教師ごとに API 呼び出しを行う必要がありますか?
現在、ネストされたモデルを保存できないことはわかっていますが、教師レベルで保存できるかどうか知りたいです。ありがとう!
これは少し前に尋ねられたことは知っていますが、自分でこれを理解しようとしているときに見つけました。
モデルのシリアライザー クラスをインスタンス化するときに渡す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 つのリソースを作成しました。それはよかったです。
ディクショナリから配列に変換する 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)
フレームワークの提案されたアーキテクチャを尊重する最善の方法は、次のような 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 メソッドを上書きする方が賢明です。
Django REST Frameworkのドキュメントの「ジェネリックビュー」ページには、ListCreateAPIViewジェネリックビューは「モデルインスタンスのコレクションを表すための読み取り/書き込みエンドポイントに使用される」と記載されています。
それが私が探し始めるところです(そして、私たちのプロジェクトでもこの機能がすぐに必要になるので、実際に見ていきます)。
GenericViewsページの例ではたまたまを使用していることにも注意してくださいListCreateAPIView
。