我正在使用Django REST framework用于API和Angular SPA与Restangular用于与API通信。有时我必须添加多个对象才能添加,我认为我可以将它们一起发送到数组中并发出一个请求。
当我尝试从Restangular中执行此操作时,我为错误的输入重现了错误。如果我尝试从REST框架Web界面添加多个对象,我将传递对象或对象数组:
// this { "text": "gdhg", },{ "text": "gdhg", },{ "text": "gdhg", }
// or this [{ "text": "gdhg", },{ "text": "gdhg", },{ "text": "gdhg", }]
但我收到了ParseError。我错了,我必须改变或如何正确地做。
答案 0 :(得分:11)
另一个支持发布数组以及发布单个对象的示例。对于寻找这样一个例子的其他人来说,它可能会有用。
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)
答案 1 :(得分:6)
我不确定问题是否仍然存在。但是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方法,则期望列表(可迭代)作为方法的参数(当您发布列表时)而不仅仅是单个对象。
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)
答案 2 :(得分:3)
以下是使用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)
这里重要的部分是many=True
方法的get_serializer()
参数。然后,为了使Angular能够很好地使用它,您可以将服务工厂定义为:
.factory('Something', ['$resource', function ($resource) {
return $resource(
"url_to_something",
{},
{
save: {
method: 'POST',
isArray: true
}
}
);
}])
重要部分是isArray: true
。如果您想保留发布单个JSON对象,可以将上面的save
更改为saveBulk
或类似内容。
答案 3 :(得分:0)
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)
让您的视图继承自此mixin类,以自动确定是否应使用many=True
序列化程序。
答案 4 :(得分:0)
如果要发布列表,则必须传递JSON
编码数据。
headers = {"Token": "35754sr7cvd7ryh454"}
recipients = [{'name': 'Ut est sed sed ipsa',
'email': 'dogoka@mailinator.com',
'group': 'signers'},
{'name': 'Development Ltda.',
'email': 'test@test.com',
'group': 'signers'}
]
requests.post(url, json=recipients, headers=headers)
requests.post(URL, json =收件人,标头=标头)
使用json
关键字参数(而不是data
),以便将数据编码为JSON
,并将Content-Type header
设置为application/json
。
默认情况下,Django Rest Framework假定您将其传递给单个对象。若要序列化查询集或对象列表而不是单个对象实例,请在实例化序列化程序时传递many=True
标志。然后,您可以传递查询集或要序列化的对象列表。
为此,您必须覆盖视图的.create()
方法:
def create(self, request, *args, **kwargs):
many = True if isinstance(request.data, list) else False
serializer = self.get_serializer(data=request.data, many=many)
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)
文档:https://www.django-rest-framework.org/api-guide/serializers/#dealing-with-multiple-objects