DRF框架(四)——单整体改(put)、单局部改(patch)、群局部改(patch)
单整体改 单指的是单独一条数据,整体指这条数据的设置不为空字段都必须传值修改
基于上篇文章的代码修改,序列化层不用变,只修改views.py
1)单整体改,说明前台要提供修改的数据,修改之后保存的数据需要校验,校验的数据应该在实例化“序列化类对象”时,赋值给data
2)修改,就必须明确被修改的模型类对象,并在实例化“序列化类对象”时,赋值给instance,必须赋值给instance
3)整体修改,所有校验规则有required=True的字段,都必须提供,因为在实例化“序列化类对象”时,参数partial默认为False 注:如果partial值设置为True,就是可以局部改
)单整体修改,一般用put请求:
V2BookModelSerializer(
instance=要被更新的对象,
data=用来更新的数据,
partial=默认False,必须的字段全部参与校验
)
)单局部修改,一般用patch请求:
V2BookModelSerializer(
instance=要被更新的对象,
data=用来更新的数据,
partial=设置True,必须的字段都变为选填字段
)
注:partial设置True的本质就是使字段 required=True 校验规则失效
请求方法:put 整体修改
请求参数:pk从路由传参,修改的数据通过数据包json传递
请求接口: http://127.0.0.1:8080/app01/v3/books/pk/
视图层:views.py
#单整体改 对 v3/books/pk/ 传的参数是与model对应的字典 {name|price|publish|authors}在json中传递
class V3Book(APIView):
def put(self,request,*args,**kwargs):
request_data = request.data
pk = kwargs.get('pk')
#先获取要修改的对象
try:
old_book_obj = models.Book.objects.get(pk=pk,is_delete=False)
except:
#当输入不存在的pk
return Response({
'status':1,
'msg':'参数错误'
})
book_ser = serializers.V2BookModelSerializer(instance=old_book_obj,data=request_data,partial=False)
book_ser.is_valid(raise_exception=True)
book_obj = book_ser.save() return Response({
'status':0,
'msg':'ok',
'results':serializers.V2BookModelSerializer(book_obj).data
})
单整体修改注意点(******)
1.需要修改的数据通过data传递
2.需要修改的模型类对象必须传递给instance
3.参数partial设置为False (默认是False,这里不设置也行)
单局部修改
单整体修改和单局部修改只有一点不相同:
设置参数partial=True,就变成单局部修改,修改的参数就不必全部传,想修改什么数据就传什么数据
单局部修改和群局部修改整合 ListSerializer辅助(群增,群改)
当一个序列化器在带有many=True选项被序列化时,将创建一个ListSerializer实例,该序列化器类将成为ListSerializer类的子类。
当你需要自定义多个对象的行为时(比如群增,群改),你需要手动定制ListSerializer类的一些行为。
可以通过在自定义序列化器的Meta类下面的list_serializer_class来绑定你需要的的ListSerializer类
序列化层 serializer.py
群改需要设置ListSerializer,创建V2BookListSerializer继承ListSerializer,重写update方法
# 重点:ListSerializer与ModelSerializer建立关联的是: 在ModelSerializer的Meta类中设置 list_serializer_class
class V2BookListSerializer(ListSerializer):
def update(self, instance, validated_data): # print(instance) # 要更新的对象们
# print(validated_data) # 更新的对象对应的数据们
# print(self.child) # 服务的模型序列化类 - V2BookModelSerializer
for index, obj in enumerate(instance):
self.child.update(obj, validated_data[index])
return instance # 原模型序列化类变化
class V2BookModelSerializer(ModelSerializer):
class Meta:
# 群改,list_serializer_class是固定的key写法,直接转入V2BookListSerializer类的 update 方法
list_serializer_class = V2BookListSerializer
update方法源码分析: update方法里面没写东西
群增不需要重写create方法,因为源码中ListSerializer走的就是ModelSerializer的create方法
create方法源码分析:
群局部修改
请求方式:patch
请求参数:
单局部修改: v3/books/pk/ pk通过路由传参,修改数据通过json传参
群局部修改: v3/books/ 修改的数据都是从json传递 eg:[{'pk':1,'name':'花果山'},{'pk':2,'price':3.33}]
请求接口:http://127.0.0.1:8080/app01/v3/books/pk/
视图层:views.py
#单局部改和群局部改整合
#单局部改:对 v3/books/pk/ pk通过路由传参,修改数据选择传参,通过数据包json传递
#群局部修改:v3/books/ 修改数据通过数据包传递,设置成列表格式 [{pk:1,name:123},{pk:3,price:7},{pk:7,publish:2}]
def patch(self,request,*args,**kwargs):
request_data = request.data #数据包数据
pk = kwargs.get('pk')
# 将单改,群改的数据都格式化成 pks=[要需要的对象主键标识] | request_data=[每个要修改的对象对应的修改数据]
if pk and isinstance(request_data,dict): #单改
pks = [pk,]
request_data = [request_data,]
elif not pk and isinstance(request_data,list): #群改
pks = []
# 遍历前台数据[{pk:1, name:123}, {pk:3, price:7}, {pk:7, publish:2}],拿一个个字典
for dic in request_data:
pk=dic.pop('pk',None) #返回pk值
if pk:
pks.append(pk)
#pk没有传值
else:
return Response({
'status':1,
'msg':'参数错误'
})
else:
return Response({
'status': 1,
'msg': '参数错误'
})
# pks与request_data数据筛选,
# 1)将pks中的没有对应数据的pk与数据已删除的pk移除,request_data对应索引位上的数据也移除
# 2)将合理的pks转换为 objs
objs = []
new_request_data = []
for index,pk in enumerate(pks):
try:
#将pk合理的对象数据保存下来
book_obj = models.Book.objects.get(pk=pk,is_delete=False)
objs.append(book_obj)
#对应索引的数据也保存下来
new_request_data.append(request_data[index])
except:
# 重点:反面教程 - pk对应的数据有误,将对应索引的data中request_data中移除
#在for循环中不要使用删除
# index = pks.index(pk)
# request_data.pop(index)
continue
#生成一个serializer对象
book_ser = serializers.V2BookModelSerializer(instance=objs,data=new_request_data,partial=True,many=True)
book_ser.is_valid(raise_exception=True)
book_objs = book_ser.save() return Response({
'status':0,
'msg':'ok',
'results':serializers.V2BookModelSerializer(book_objs,many=True).data
})
思路:
1.先将单改,群改的数据都格式化成 pks=[要需要的对象主键标识] | request_data=[每个要修改的对象对应的修改数据]
2.pks与request_data数据筛选,
将pks中的没有对应数据的pk与数据已删除的pk移除,request_data对应索引位上的数据也移除
将合理的pks转换为 objs
注意点:
1.本篇文章讲了局部修改patch,和整体修改put,都需要设置参数instance传入的是要修改的对象,data传入的是修改的数据
2.群修改的话需要使用ListSerializer,重写update方法
关于使用修改为什么要用instance传参 (源码分析)
修改之后数据使用save()保存,从视图的save()点击进去查看源码,下面是BaseSerializer类中的save
在这判断是否有instance属性
有的话就走update()方法,所以我们在做修改(put,patch)的时候就要传入instance。 没有的话就走create(),创建一条新数据
源码中发现:如果你使用的是Serializer,在视图使用save方法保存数据,但是通过源码发现Serializer类中没有save方法所以只能从他继承的BaseSerializer中走save方法。你使用的是ModelSerializer,因为ModelSerializer类中没有save方法,只能去他继承的Serializer类中找save方法,Serializer类中也没有save方法,所以最后不管你用的是Serializer还是ModelSerializer都要去BaseSerializer中找save方法。然后从save方法中去实现update和create方法。
拓展:
顺带提一嘴,在BaseSerializer中的update和create方法都是不起作用的,从下面源码可以看出,所以如果你的Serializer类是走的BaseSerializer的update和create方法,那么你就必须在你的Serializer类中重写update和create方法
因为ModelSeerializer中有create和update方法,而且都是有用的,所以在ModelSeerializer中不需要重写create和update方法
DRF框架(四)——单整体改(put)、单局部改(patch)、群局部改(patch)的更多相关文章
- DRF框架和Vue框架阅读目录
Vue框架目录 (一)Vue框架(一)——Vue导读.Vue实例(挂载点el.数据data.过滤器filters).Vue指令(文本指令v-text.事件指令v-on.属性指令v-bind.表单指令v ...
- 整体单改,单局部改,整体局部改,ListSerializer类
复习 """ 1.ModelSerializer序列化类 models.py class BaseModel(models.Model): is_delete = mod ...
- drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)
ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...
- 第四章:Django表单 - 1:使用表单
假设你想从表单接收用户名数据,一般情况下,你需要在HTML中手动编写一个如下的表单元素: <form action="/your-name/" method="po ...
- (四)Jquery Mobile表单
Jquery Mobile表单与列表 一.JM表单 1.表单 普通html表单 效果: 2.只能输入数字的表单 效果: ...
- DRF框架之认证组件用法(第四天)
1. 什么是drf 框架的认证组件: auth 就等于是jango中的Auth模块,Auth是自带session信息,但是 drf的认证组件可以自定义token携带过去,去判断用的 2.如何实现认证呢 ...
- Html5学习进阶四 表单元素和表单属性
HTML5 的新的表单元素: HTML5 拥有若干涉及表单的元素和属性. 本章介绍以下新的表单元素: datalist keygen output 浏览器支持 Input type IE Firefo ...
- 工作流Activiti框架中表单的使用!详细解析内置表单和外置表单的渲染
Activiti中的表单 Activiti提供了一种方便而且灵活的方式在业务流程中以手工方式添加表单 对表单的支持有2种方式: 通过表单属性对内置表单进行渲染 通过表单属性对外置表单进行渲染 表单属性 ...
- drf 框架
一. drf简介 drf框架,全程: django-rest framework , rest是插件名字,django插件的名字叫rest,framework是框架的意思 二. 接口 在平时生活 ...
随机推荐
- Thanos prometheus 集群以及多租户解决方案docker-compose 试用(一)
prometheus 是一个非常不多的metrics 监控解决方案,但是对于ha 以及多租户的处理并不是很好,当前有好多解决方案 cortex Thanos prometheus+ influxdb ...
- [Java] key
Z2VueW1vJTIwJTI2JTI2JTI2JTIwMTYzJTNBJTBBdXNyJTIwLSUyMHd1a29uZ3N1bjEyMzQlMjAlMjMlMjAxNjMuc3VmZml4JTIw ...
- 【cf比赛记录】Codeforces Round #601 (Div. 2)
Codeforces Round #601 (Div. 2) ---- 比赛传送门 周二晚因为身体不适鸽了,补题补题 A // http://codeforces.com/contest/1255/p ...
- CF859E Desk Disorder
传送门 Luogu Solution 好好思考一下,发现人和座位构成的是一个二分图这还用想? 那么这个时候发现其实我们要求的就是这个二分图完全匹配的方案数,考虑在二分图上的一个连通块,如果是树,那么就 ...
- linux jar/war包 后台运行
1. 基础版,当前ssh窗口锁定,按CTRL+C打断程序运行:或关闭窗口,程序退出 java -jar flowable-modeler.war 2. 改进版,当前ssh窗口不锁定,窗口关闭时,程序终 ...
- Linux里使用rz和sz命令
lrzsz是一个unix通信套件提供的X,Y,和ZModem文件传输协议,官网:http://freecode.com/projects/lrzsz/ windows 需要向centos服务器上传文件 ...
- 5098: [BZOJ1098][POI2007]办公楼biu
5098: [BZOJ1098][POI2007]办公楼biu 没有数据结构就很棒 一个看上去非常玄学的代码 const int N=1e5+10,M=2e6+10; int n,m; int fa[ ...
- 冰多多团队-第五次Scrum会议
冰多多团队-第五次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 zpj 部分Action整合, 接入语音接口,整合项目解决兼容性问题 ASR bug修复 牛雅哲 跑通了科大讯飞语法识别的 ...
- Cesium 1.54评测 【转】
重要功能评测 3dtiles数据上画线和贴纹理 3dtiles数据上画线和贴纹理 把线条贴到3dtiles上需要用到两个属性:clampToGround和classificationType. c ...
- latch - undo global data等待事件分析
一环境跑压力测试的时候,标题所述等待事件在top N中.不用查,也知道是因为undo竞争的事件. 根据metalink文档解释,是由于undo表空间不足引起的. This implies that s ...