接上篇
前面分开讲了反序列化输出(参数传instance),和序列化(参数传data)。
实际上
- 可以同时传 (
原有值
instance) 和(前端传入值
data) 参数- 但传了
data
,需要用.is_valid (),没传,不能用
- 但传了
- 使用serializer.data 就是作为
序列化后输出的数据
- 如果光传instance,就把instance数据输出
- 如果传了data,输出值serilizer.data就是校验通过后的值serilizer.validated_data再进行变化后的值(如:有字段write_only=True,那么serilizer.data就没有这个字段)如下图
方法
该方法会触发create方法,或者 update方法,serializer.data就会从create方法,或者 update方法返回出来
使用它时,要先进行 is_valid(), 即(同时至少需要传data)
-
serializers_obj= TestSerilizer1(data=body) ,如果仅传(
前端传入值
data) ,就调用create方法
-
同时传 (
原有值
instance) 和(前端传入值
data) 参数,就调用update方法
序列化器类中重写 create() 方法
修改视图函数,改用save()
:
同时给序列化器类中,写一个create方法
再调用 /projects 进行 新增时, 执行save()方法,会去执行序列化器里面的 create()
save(),还能传参数,相当于修改serializer.validated_data ,如下
save(newname=“”) 也可以传参数,数据也是拼在 validated_data数据 或 覆盖(如果有同样的)
如果 save(name="始终是这个名字")
,这样写的话,就会覆盖前端传的name参数
在正常使用中,create方法里面就放新增 的代码,update里面就方法更新的代码
(后面讲的模型序列化器,会自带有create和update方法,就不用再写了)
重写create、update实际案例
补充:在create 方法,和upate方法里面,
- 场景1:可以增加 模型类中没有的 序列化字段进行返回 :
- 场景2 :【模型类中没有字段,序列化器中有的字段】 进行处理 (如下场景2)
场景1
如下:有这么一种登陆场景
登陆成功后,返回中需要加上token 字段。 但是token不是用户模型中的东西,要输出
- 就要在序列化器中增加一个token字段。
- 修改create方法, 把结果,加一个token字段。
场景2
:
如登录时,要用到短信验证码进行校验,但它在模型类中没有的(不需要入库)。
- 就可以定义 一个 sms_code ,定义成 write_only =True, 需要传。用来校验,
- 然后又在某个地方把它删除掉 进行validated_data。pop(“sms_code”)
- 可以在create方法中给它pop掉 ,
- 也可以在is_valid()校验的过程中(参数规则—>单字段校验---->多字段联合校验方法)
多字段联合校验方法里 def validate(self, attrs):
场景3
柠檬班的项目:修改了项目序列化器的新增 create方法,让它可以项目的同时,可以新增一个debugtalk
模型序列化器类
之前是痛点:
- 在序列化器类中,单独定义每个字段(如果模型类中有100个字段,就要单独定义100个)
现在:继承ModelSerializer 它,就可以快速生成代码
作用有两点
- 自动转化各字段成序列化器类中的字段
- 提供了create方法和 update方法
怎么做
:
- 需要添加model参数,
- 和 fields参数,或者exclude (详见下面)
model写法 、fields写法、 read_only_fields
# 需要在 Meta 中 ,指定 model 和 fields
class ProjectsModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
fields = '__all__' # '__all__'
修改已有代码
fields 的写法
fields参数,有三种
- fields = [“name”,“leader”]
- fields = ‘all’
- exclude = [“name”,“leader”] # 指定哪些不需要,和 第一个相反
可以批量设置 一些 字段 为 read_only = True
read_only_fields=[“name”,“leader”]
[模型序列化器】生成字段规则不符合怎么办:
null=True \ default="" \ unique=True max_length ,这些都可以自动生成规则。
但是有一些是不用自动生成的,怎么办?
-
方式1:
重写
自定义的同名字段,优先级大于 自动生成的序列化字段( 注: 字段要加到fields
中(如果是’_-all__ ’ 就不用添加了)
-
方式2:
稍微修改
的方式 ,可以在extra_kwargs 对某个字段进行任意的修改(如果自动化生成的序列化器字段只有少量不满足,就可以进行微调)
class Meta:
model = Projects_test
fields = '__all__'
# 可以单独修改一些字段的校验
extra_kwargs = {
'name': {"label":"新的描述",
"max_length": 6 , "min_length": 3,"error_messages": {'max_length': '太长了', 'min_length': '太短了'}},
'leader': { }
}
field 字段要返回完整
fields = '__all__' 可能是不够的,比如下面三种情况
情况1、外键(如项目表)
情况2、用户序列化器的 确认密码字段
一般设置成write_only, 只是输入时要用到,但也要写到 field 中
情况3、用户序列化器的 token字段
一般设置read_only, 只做输出,但也要写到 field 中
[模型序列化器】已有create和update方法
因为序列化器继承的是ModelSerializer,这里面已经写好了create 和update方法。
但也是可以重写的,如下图的
但也可重写create()
上述的情况2-注冊用戶時要确认密码,但是正在创建时又不要
如下,是再create方法中进行,删除多余的数据 (如上面说到情况2)
上述情况3-登录接口要返回个token
instance= super().create(validated_data) (因为父类创建后,返回的就是模型对象)
instance.token="*****"
return instance
序列化器中数据流转
用新增举例:
serializers_obj= TestSerilizer1(data=body)
if serializers_obj.is_valid():
serializers_obj.save()
过程1:在is_valid()的过程中,会校验body是否满足规则,得到serializer.validated_data
- 过程中可以使用【多字段联合校验方法】def validate, 进行自定义的校验如,密码和确认密码两个字段数据是否一致
- 把前端body中多传的参数,进行处理,如把验证字段在这里校验,然后删除
过程2:在create() 和 update方法() 里, 会把serializer.validated_data 序列化变成serializer.data的(如,write_only为true的,是不会输出的)
- 在这个过程中,可以用save()方法改变serializer.validated_data
- 也可以在create,和update方法里,把serializer.validated_data进行处理了