前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DRF系列总结三:批量更新接口的一种写法

DRF系列总结三:批量更新接口的一种写法

原创
作者头像
高木工
修改2019-09-24 13:31:11
4.7K0
修改2019-09-24 13:31:11
举报
文章被收录于专栏:运维开发

项目中需要写一个批量更新资源的接口:/matrix/batch_upate/,请求参数如下:

代码语言:javascript
复制
[
    {
        "id": 71,
        "priority": "1"
    },
    {
        "id": 69,
        "priority": "1"
    },
    {
        "id": 70,
        "priority": "2"
    }
]

一次接口提交,批量更新三条数据的priority字段 ,在DRF框架中,要实现这样的接口,需要在视图类PriorityMatrixViewSet中添加一个自定义接口,比如batch_update方法,并定义序列化类MatrixListSerializer对接口参数进行校验,最后再定义一个批量更新的方法batch_update,并在视图类中校验通过后进行批量更新操作,如图所示:

序列化类
序列化类
视图类
视图类

测试一下接口,立刻报错了:

报错了
报错了

序列化类中新增的方法batch_update不见了?明明我定义的类是MatrixListSerializer,这里报错为什么是ListSerializer

于是,看了下MatrixListSerializer的基类ModelSerializer的定义,并顺着往上捋,找到了类创建和初始化的地方:__new__方法和__init__方法:

捋一下基类
捋一下基类

众所周知,__new__方法创造了对象,__init__方法进一步修改了__new__方法创造的对象,从前者的注释可以看出,作者对__new__方法做了个小动作:根据many=True的属性,返回了默认的列表序列化类ListSerializer,这就解释了前面的报错。同时从many_init方法中可以看出,我们可以自定义列表序列化类:

动态返回序列化类
动态返回序列化类

默认的序列化类中写了明确的注释,它不知道如何批量更新(最多支持批量创建),但是你可以自己扩展,继承这个类,并重写update方法即可。

列表序列化类
列表序列化类

最终,我们可以通过Meta类的list_serializer_class属性来启用我们自定义的序列化类:

自定义序列化类
自定义序列化类

接下来,我们在update方法中实现了批量更新操作,但是,这种写法需要多次数据库交互,需要频繁建立数据库连接,有没有更好的解法?

一条sql
一条sql

不想重复造轮子,逛了一下github,发现真的有人提供了一个工具:

bulk_update
bulk_update

啥原理?看下bulk_update方法,跳过前面的逻辑,看下最后神奇的sql语句吧:

bulk_update
bulk_update

把sql语句打印出来,豁然开朗,原来是结合update和case when的条件更新sql

条件更新sql
条件更新sql

最后,我们借助这个工具,就可以通过一次sql操作实现批量更新了:

最后的update
最后的update

最后,总结一下,DRF默认是不支持批量更新接口的,需要自己实现一个自定义接口,这个接口的实现方式有很多种,上面给大家列出了我的解决方法,希望能启发到你。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档