08 ModelSerializer 序列化组件
一、ModelSerializer序列化组件
ModelSerializer 类是将序列化和反序列化都放在一个自定义类中
# 这是将序列化和反序列化的都放在一个自定义类中
from rest_framework.serializers import ModelSerializer
from .. import models
class UserModelSerializer(ModelSerializer):
# 将序列化的类与model进行绑定
# 设置序列化与反序列化所有字段(并划分序列化字段与反序列化字段)
# 设置反序列化的局部与全局钩子
# 自定义反序列化字段,校验规则只能在声明自定义反序列化字段时设置,且一定是write_only
re_pwd = serializers.CharField(min_length=3, max_length=64, write_only=True)
class Meta:
model = models.User
fields = ['name', 'pwd', 'age','sex', 'height', 're_pwd','gender']
extra_kwargs = {
'pwd': {
'write_only': True,
},
'name':{
'required': True,
'min_length': 3,
'error_messages': {
'required': '用户名不得为空',
'min_length': '用户名不得少于3个字符',
'max_length': '用户名不得多于64个字符'
}
},
'age':{
'required': True, # 数据库有默认值或可以为空字段,required默认为False
'min_value': 0,
'error_messages': {
'required':'年龄不能为空'
}
},
'gender':{
'read_only':True
}
}
# 局部钩子校验方法
# 对前台发过来的name字段除了系统校验后,在进行单独的校验
def validate_name(self, value):
# value就是name值
if 'a' in value.lower(): # 判断a字母在不在name里面
# 如果在,直接抛异常
raise serializers.ValidationError('名字中不能有a字符')
# 不在就直接返回name
return value
# 全局钩子用来校验密码和确认密码是否一致
def validate(self, attrs):
pwd = attrs.get('pwd')
re_pwd = attrs.pop('re_pwd') # 将前台传过来的字典中的re_pwd的取出,并且移除
if re_pwd != pwd:
# 如果是全局校验的话,异常是以字典的形式抛出,如下
raise serializers.ValidationError({'re_pwd': '两次密码不一致'})
return attrs
二、总结
1. 将序列化与反序列化功能整合到一个类,这个类继承 `ModelSerializer`来实现
2. 继承`ModelSerializer`类的资源序列化类内部包含三部分,
Meta子类,
局部钩子、
全局钩子
注:create和update方法ModelSerializer已经重写了,使用不需要重写
3. 在Meta子类中:
用model来绑定所关联的Model类
用fields来设置所有的序列化反序列化字段
用extra_kwargs来设置系统的校验规则
4. 重要字段校验规则
read_only校验规则:代表该字段只参与序列化,
不参与反序列化进行校验,
就是校验数据传来了height这个参数,
不会对数据进行校验只会返回原先的数据或者是默认的数据
write_only校验规则:只参与反序列化
设置这个就是在反序列化的时候不会返回给前台,不会序列化
required校验规则:代表该字段在反序列化,在数据库中有默认值或可以为空字段,
required默认为false,前台发数据不会进行校验,只有true时才进行校验
如果一个字段有默认值或可以为空,没设置required,默认False,反之默认为True
如果一个Model字段没有设置read_only也没write_only,该字段默认序列化反序列化
5. 自定义序列化字段:
在Model类中,
定义方法属性(可以返回特殊值,还可以完成连表操作),
在序列化类的fields属性中可以选择性插拔(重要)
6. 自定义反序列化字段:在Serializer类中,自定义校验字段,校验规则也只能在声明字段时设置,自定义的反序列化字段(如re_pwd),必须设置write_only为True