私は Django RESTフレームワーク をAPIに、Angular SPA with RestangularをAPIとの通信に使用しています。場合によっては、さらに追加する必要があります。追加するオブジェクトは複数あり、それらを配列でまとめて送信し、1つのリクエストを行うことができると思います。
Restangularからこれを実行しようとすると、間違った入力に対してエラーが発生します。 RESTフレームワークWebインターフェイスから複数のオブジェクトを追加しようとすると、オブジェクトまたはオブジェクトの配列を渡します。
// this { "text": "gdhg", },{ "text": "gdhg", },{ "text": "gdhg", }
// or this [{ "text": "gdhg", },{ "text": "gdhg", },{ "text": "gdhg", }]
しかし、ParseErrorを受け取ります。私が間違っている場合、私が変更しなければならないこと、またはそれを適切に行う方法。
配列の投稿と単一のオブジェクトの投稿をサポートする別の例。そのような例を探している他の人にとって役立つかもしれません。
class BookViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
"""
ViewSet create and list books
Usage single : POST
{
"name":"Killing Floor: A Jack Reacher Novel",
"author":"Lee Child"
}
Usage array : POST
[{
"name":"Mr. Mercedes: A Novel (The Bill Hodges Trilogy)",
"author":"Stephen King"
},{
"name":"Killing Floor: A Jack Reacher Novel",
"author":"Lee Child"
}]
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
search_fields = ('name','author')
def create(self, request, *args, **kwargs):
"""
#checks if post request data is an array initializes serializer with many=True
else executes default CreateModelMixin.create function
"""
is_many = isinstance(request.data, list)
if not is_many:
return super(BookViewSet, self).create(request, *args, **kwargs)
else:
serializer = self.get_serializer(data=request.data, many=True)
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)
問題がまだ存在するかどうかはわかりません。しかし、fiverによって提案された解決策は私にはうまくいきませんでした。私にとってうまくいくのは、get_serializer
メソッドのみをオーバーライドすることです。
def get_serializer(self, instance=None, data=None, files=None, many=True, partial=False): return super(ViewName, self).get_serializer(instance, data, files, many, partial)
many=True
の引数にデフォルトのget_serializer
を設定していることに気付くと思います。それ以外は何も必要ありません。 createメソッドのオーバーライドも必要ありません。
また、ビューでpre_saveメソッドとpost_saveメソッドを定義している場合は、単一のオブジェクトだけでなく、メソッドの引数としてlist(iterable)を(リストを投稿するときに)期待します。
def post_save(self, objects, *args, **kwargs): """ In the post_save, list of obj has been created """ for obj in objects: do_something_with(obj)
Django REST Frameworkを使用してListCreateAPIViewで一括POSTを設定する例を次に示します:
_class SomethingList(generics.ListCreateAPIView):
model = Something
serializer_class = SomethingSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.DATA, 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)
_
ここで重要なのは、get_serializer()
メソッドの_many=True
_引数です。次に、Angularこれでうまくプレイできるようにするには、サービスファクトリを次のように定義できます。
_.factory('Something', ['$resource', function ($resource) {
return $resource(
"url_to_something",
{},
{
save: {
method: 'POST',
isArray: true
}
}
);
}])
_
重要な部分は_isArray: true
_です。単一のJSONオブジェクトの投稿を保持したい場合は、上記のsave
をsaveBulk
などに変更できます。
構築 vibhorの答え :
class ListableViewMixin(object):
def get_serializer(self, instance=None, data=None, many=False, *args, **kwargs):
return super(ListableViewMixin, self).get_serializer(
instance=instance, data=data, many=isinstance(instance, list) or isinstance(data, list),
*args, **kwargs)
ビューをこのミックスインクラスから継承して、many=True
シリアライザーを使用する必要があります。