问题描述
我正在阅读有关自定义多个更新的信息。,我还没有想到在什么情况下调用自定义 ListSerializer
更新方法。我想一次更新多个对象,我不担心现在多次创建或删除。
I'm reading about customizing multiple update here and I haven't figured out in what case the custom ListSerializer
update method is called. I would like to update multiple objects at once, I'm not worried about multiple create or delete at the moment.
从文档中的示例:
# serializers.py
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
# custom update logic
...
class BookSerializer(serializers.Serializer):
...
class Meta:
list_serializer_class = BookListSerializer
我的ViewSet
# api.py
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
我的url设置使用 DefaultRouter
# urls.py
router = routers.DefaultRouter()
router.register(r'Book', BookViewSet)
urlpatterns = patterns('',
url(r'^api/', include(router.urls)),
...
所以我使用 DefaultRouter
设置,以便 / api / Book /
将使用 BookSerializer
。
So I have this set up using the DefaultRouter
so that /api/Book/
will use the BookSerializer
.
一般的想法是,如果我将JSON对象的数组POST / PUT / PATCH为 / api / Book /
然后串行器应该切换到 BookListSerializer
?
Is the general idea that if I POST/PUT/PATCH an array of JSON objects to /api/Book/
then the serializer should switch over to BookListSerializer
?
我已经尝试过POST / PUT / PATCH JSON数据列表到这个 / api / Book /
:
I've tried POST/PUT/PATCH JSON data list to this /api/Book/
that looks like:
[ {id:1,title:thing1}, {id:2, title:thing2} ]
但是似乎仍然使用 BookSerializer
来处理数据,而不是 BookListSerializer
。如果我通过POST提交,我得到无效的数据。预期一个字典,但得到列表
。如果我通过PATCH或PUT提交,那么我得到一个方法'PATCH'不允许
错误。
but it seems to still treat the data using BookSerializer
instead of BookListSerializer
. If I submit via POST I get Invalid data. Expected a dictionary, but got list
. and if I submit via PATCH or PUT then I get a Method 'PATCH' not allowed
error.
问题:
我必须调整 DefaultRouter
或的
允许列表的POST / PATCH / PUT?通用视图没有设置为使用 allowed_methods
code> BookViewSet ListSerializer
?
Question:Do I have to adjust the allowed_methods
of the DefaultRouter
or the BookViewSet
to allow POST/PATCH/PUT of lists? Are the generic views not set up to work with the ListSerializer
?
我知道我可以编写自己的列表解串器为此,但我正在努力保持最新的DRF 3中的新功能,它看起来应该可以工作,但我只是错过了一些约定或一些选项。
I know I could write my own list deserializer for this, but I'm trying to stay up to date with the new features in DRF 3 and it looks like this should work but I'm just missing some convention or some option.
推荐答案
默认情况下,Django REST框架假定您不处理批量数据创建,更新或删除。这是因为99%的人不处理批量数据创建,而。
Django REST framework by default assumes that you are not dealing with bulk data creation, updates, or deletion. This is because 99% of people are not dealing with bulk data creation, and DRF leaves the other 1% to third-party libraries.
在Django REST框架2.x和3.x中,第三方软件包。
In Django REST framework 2.x and 3.x, a third party package exists for this.
现在,您正在尝试批量创建,但您会收到一条错误,说明
Now, you are trying to do bulk creation but you are getting an error back that says
这是因为您正在发送一个对象列表来创建,而不是只发送一个。您可以通过以下几种方式解决问题,但最简单的方法是到。
This is because you are sending in a list of objects to create, instead of just sending in one. You can get around this a few ways, but the easiest is to just override get_serializer
on your view to add the many=True
flag to the serializer when it is a list.
def get_serializer(self, *args, **kwargs):
if "data" in kwargs:
data = kwargs["data"]
if isinstance(data, list):
kwargs["many"] = True
return super(MyViewSet, self).get_serializer(*args, **kwargs)
这将允许Django REST框架知道自动使用 ListSerializer $批量创建对象时,c $ c>现在,对于其他操作(如更新和删除),您将需要覆盖默认路由。我将假设您正在使用由Django REST提供的,但是您可以随意使用任何您想要的方法名称。
This will allow Django REST framework to know to automatically use the ListSerializer
when creating objects in bulk. Now, for other operations such as updating and deleting, you are going to need to override the default routes. I'm going to assume that you are using the routes provided by Django REST framework bulk, but you are free to use whatever method names you want.
您将需要添加批量的方法 PUT
和 PATCH
给视图。
You are going to need to add methods for bulk PUT
and PATCH
to the view as well.
from rest_framework.response import Response
def bulk_update(self, request, *args, **kwargs):
partial = kwargs.pop("partial", False)
queryset = self.filter_queryset(self.get_queryset))
serializer = self.get_serializer(instance=queryset, data=request.data, many=True)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
def partial_bulk_update(self, *args, **kwargs):
kargs["partial"] = True
return super(MyView, self).bulk_update(*args, **kwargs)
将不会开箱即用,因为Django REST框架默认不支持批量更新。这意味着您也。当前代码将处理批量更新,就像您正在尝试更新整个列表一样,这是旧的批量更新程序包以前的工作原理。
This won't work out of the box as Django REST framework doesn't support bulk updates by default. This means you also have to implement your own bulk updates. The current code will handle bulk updates as though you are trying to update the entire list, which is how the old bulk updating package previously worked.
虽然您没有问对于批量删除,这不会特别困难。
While you didn't ask for bulk deletion, that wouldn't be particularly difficult to do.
def bulk_delete(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
self.perform_delete(queryset)
return Response(status=204)
这与删除所有对象的效果相同,与旧的批量插件相同。
This has the same effect of removing all objects, the same as the old bulk plugin.
这段代码都没有被测试。如果不起作用,请将其视为一个详细示例。
这篇关于如何将json数据发布/放置到ListSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!