如何 PUT/POST JSON 数据到 ListSerializer?
How can I PUT/POST JSON data to a ListSerializer?
我正在阅读有关自定义多个更新 here 的内容,但我还没有弄清楚在什么情况下会调用自定义 ListSerializer
更新方法。我想一次更新多个对象,我现在不担心多个创建或删除。
来自文档中的示例:
# 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
还有我的视图集
# 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
。
一般的想法是,如果我 POST/PUT/PATCH 一个 JSON 对象的数组到 /api/Book/
那么序列化程序应该切换到 BookListSerializer
吗?
我试过 POST/PUT/PATCH JSON 数据列表到这个 /api/Book/
看起来像:
[ {id:1,title:thing1}, {id:2, title:thing2} ]
但它似乎仍然使用 BookSerializer
而不是 BookListSerializer
来处理数据。如果我通过 POST 提交,我会得到 Invalid data. Expected a dictionary, but got list
。如果我通过 PATCH 或 PUT 提交,则会收到 Method 'PATCH' not allowed
错误。
问题:
我是否必须调整 DefaultRouter
的 allowed_methods
或 BookViewSet
以允许 POST/PATCH/PUT 个列表?通用视图是否未设置为与 ListSerializer
一起使用?
我知道我可以为此编写自己的列表反序列化器,但我正在努力了解 DRF 3 中的新功能,看起来这应该可行,但我只是缺少一些约定或一些选择。
默认情况下,Django REST 框架假定您不处理批量数据创建、更新或删除。这是因为 99% 的人都没有处理批量数据创建,DRF leaves the other 1% to third-party libraries.
在 Django REST 框架 2.x 和 3.x 中,一个第三方包 exists for this。
现在,您正在尝试进行批量创建,但您收到一条错误消息,上面写着
Invalid data. Expected a dictionary, but got list
这是因为您要发送要创建的对象列表,而不是只发送一个。您可以通过几种方式解决这个问题,但最简单的方法是 override get_serializer
on your view to add the many=True
flag 到序列化程序,当它是一个列表时。
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
。现在,对于更新和删除等其他操作,您将需要覆盖默认路由。我假设您正在使用 routes provided by Django REST framework bulk,但您可以随意使用任何您想要的方法名称。
您还需要将批量 PUT
和 PATCH
的方法添加到视图中。
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 框架不支持批量更新。这意味着你也 have to implement your own bulk updates。当前代码将处理批量更新,就好像您正在尝试更新整个列表一样,这是旧的批量更新包以前的工作方式。
虽然您没有要求批量删除,但这并不是特别困难。
def bulk_delete(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
self.perform_delete(queryset)
return Response(status=204)
这与删除所有对象的效果相同,与旧的批量插件相同。
None 这段代码已经过测试。如果还不行,就当做一个详细的例子吧。
我正在阅读有关自定义多个更新 here 的内容,但我还没有弄清楚在什么情况下会调用自定义 ListSerializer
更新方法。我想一次更新多个对象,我现在不担心多个创建或删除。
来自文档中的示例:
# 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
还有我的视图集
# 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
。
一般的想法是,如果我 POST/PUT/PATCH 一个 JSON 对象的数组到 /api/Book/
那么序列化程序应该切换到 BookListSerializer
吗?
我试过 POST/PUT/PATCH JSON 数据列表到这个 /api/Book/
看起来像:
[ {id:1,title:thing1}, {id:2, title:thing2} ]
但它似乎仍然使用 BookSerializer
而不是 BookListSerializer
来处理数据。如果我通过 POST 提交,我会得到 Invalid data. Expected a dictionary, but got list
。如果我通过 PATCH 或 PUT 提交,则会收到 Method 'PATCH' not allowed
错误。
问题:
我是否必须调整 DefaultRouter
的 allowed_methods
或 BookViewSet
以允许 POST/PATCH/PUT 个列表?通用视图是否未设置为与 ListSerializer
一起使用?
我知道我可以为此编写自己的列表反序列化器,但我正在努力了解 DRF 3 中的新功能,看起来这应该可行,但我只是缺少一些约定或一些选择。
默认情况下,Django REST 框架假定您不处理批量数据创建、更新或删除。这是因为 99% 的人都没有处理批量数据创建,DRF leaves the other 1% to third-party libraries.
在 Django REST 框架 2.x 和 3.x 中,一个第三方包 exists for this。
现在,您正在尝试进行批量创建,但您收到一条错误消息,上面写着
Invalid data. Expected a dictionary, but got list
这是因为您要发送要创建的对象列表,而不是只发送一个。您可以通过几种方式解决这个问题,但最简单的方法是 override get_serializer
on your view to add the many=True
flag 到序列化程序,当它是一个列表时。
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
。现在,对于更新和删除等其他操作,您将需要覆盖默认路由。我假设您正在使用 routes provided by Django REST framework bulk,但您可以随意使用任何您想要的方法名称。
您还需要将批量 PUT
和 PATCH
的方法添加到视图中。
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 框架不支持批量更新。这意味着你也 have to implement your own bulk updates。当前代码将处理批量更新,就好像您正在尝试更新整个列表一样,这是旧的批量更新包以前的工作方式。
虽然您没有要求批量删除,但这并不是特别困难。
def bulk_delete(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
self.perform_delete(queryset)
return Response(status=204)
这与删除所有对象的效果相同,与旧的批量插件相同。
None 这段代码已经过测试。如果还不行,就当做一个详细的例子吧。