项目中需要写一个批量更新资源的接口:/matrix/batch_upate/,请求参数如下:
[
{
"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方法中实现了批量更新操作,但是,这种写法需要多次数据库交互,需要频繁建立数据库连接,有没有更好的解法?
不想重复造轮子,逛了一下github,发现真的有人提供了一个工具:
啥原理?看下bulk_update方法,跳过前面的逻辑,看下最后神奇的sql语句吧:
把sql语句打印出来,豁然开朗,原来是结合update和case when的条件更新sql:
最后,我们借助这个工具,就可以通过一次sql操作实现批量更新了:
最后,总结一下,DRF默认是不支持批量更新接口的,需要自己实现一个自定义接口,这个接口的实现方式有很多种,上面给大家列出了我的解决方法,希望能启发到你。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。