如何将JSON数据放入/发布到ListSerializer?

2024-09-28 22:20:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在阅读有关自定义多个更新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

如果我将一个JSON对象数组POST/PUT/PATCH到/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错误

问题: 我是否必须调整DefaultRouterBookViewSetallowed_methods以允许列表的POST/PATCH/PUT?泛型视图是否未设置为与ListSerializer一起使用

我知道我可以为此编写自己的列表反序列化程序,但我正在努力跟上DRF3中的新功能,看起来这应该可以工作,但我只是缺少一些约定或选项


Tags: pyapi列表putpostclasspatchrouter
1条回答
网友
1楼 · 发布于 2024-09-28 22:20:30

默认情况下,Django REST框架假定您不处理批量数据创建、更新或删除。这是因为99%的人没有处理批量数据创建和DRF leaves the other 1% to third-party libraries

在Django REST framework 2.x和3.x中,第三方包exists for this

现在,您正试图进行批量创建,但您得到的错误是

Invalid data. Expected a dictionary, but got list

这是因为您正在发送一个要创建的对象列表,而不是只发送一个。有几种方法可以解决这个问题,但最简单的方法是当序列化程序是一个列表时,只需override ^{} on your viewadd the ^{} 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,但是您可以自由地使用任何您想要的方法名称

您还需要向视图中添加批量PUTPATCH的方法

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)

这与删除所有对象的效果相同,与旧的批量插件相同

这些代码都没有经过测试。如果它不起作用,把它当作一个详细的例子。eem>

相关问题 更多 >