如何将JSON数据PUT/POST到ListSerializer? [英] How can I PUT/POST JSON data to a ListSerializer?

查看:25
本文介绍了如何将JSON数据PUT/POST到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

And my ViewSet

# api.py
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

以及我使用 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 BookViewSet allowed_methods ,以允许列表的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 标志到序列化程序.

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数据PUT/POST到ListSerializer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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