如何将json数据发布/放置到ListSerializer [英] How to post/put json data to ListSerializer

查看:507
本文介绍了如何将json数据发布/放置到ListSerializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读有关自定义多个更新的信息。这里,我还没有想到在什么情况下调用自定义 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 allowed_methods code> BookViewSet 允许列表的POST / PATCH / PUT?通用视图没有设置为使用 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%的人不处理批量数据创建,而 DRF离开了另外1个%到第三方库

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


无效数据。预期一个字典,但得到列表

Invalid data. Expected a dictionary, but got list

这是因为您正在发送一个对象列表来创建,而不是只发送一个。您可以通过以下几种方式解决问题,但最简单的方法是覆盖 get_serializer 您的视图在序列化程序列表中添加 many = True flag

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 现在,对于其他操作(如更新和删除),您将需要覆盖默认路由。我将假设您正在使用由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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆