二、DRF框架中序列化和反序列化
数据校验
比如
将前端传递的json格式数据转化为python中的数据类型(模型类对象)叫做反序列化
将模型类对象转化为json格式的数据叫做序列化
数据增删改查流程
增
校验请求参数-->反序列化-->保存数据-->将保存的对象序列化并返回
删
判断要删除的数据是否存在-->执行数据库删除并返回
改
判断要修改的数据是否存在-->校验请求参数-->反序列化-->保存数据-->将保存的对象序列化并返回
查
查询数据库-->将数据序列化并返回
定义序列化器注意事项
1.定义的序列化器,必须继承rest_framework中的serializers或者Serializer子类
2.定义的每一个类属性要与模型类中对应
3.默认情况下,定义了哪些类属性(序列化器字段),那么就会序列化输出哪些字段和哪些字段需要进行反序列化输入,如果不需要序列化输出,不定义即可,如果不要返回ID,可以不用定义ID
字段校验顺序:
4.字段定义时的限制(包含validators列表条目从左到右进行校验),通过之后才会开始对单字段进行校验,接下来是多字段的校验
View中进行序列化操作
a.序列化过程:将模型类对象(或查询集对象)转化为json数据
b.将模型类对象(或查询集对象)传给instance,可以进行序列化操作
c.通过序列化器ProjectSerializer对象的data属性,可以获取转化后的值
project_qs:查询到的模型类对象
ProjectSerializer:序列化器类
many=True:如果返回多条数据(列表),需要添加这个
instance:如果需要序列化输出,需要给instance传参
如:serializer = serializers.ProjectSerializer(instance=project_qs, many=True)
data:如果需要反序列化输入(数据校验),需要给data传参
is_valid():调用该方法才能进行数据校验
raise_exception=True:如果校验通过,正常返回,如果不通过,会返回相应的错误信息
serializer.validated_data:获取校验通过之后的数据
如:
serializer = serializers.ProjectSerializer(data=project_qs, many=True)
serializer.is_valid(raise_exception=True)
project=Projects.objects.creat(**serializer.validated_data)
序列化器字段释义
label,help_text选项相当于模型类中verbose_name,help_text
write_only=True,那么当前字段只能进行反序列化操作(数据校验),也不会返回给前端
read_only=True,那么当前字段只能进行序列化操作输出,不进行数据校验(也就是前端可以不用传这个值,后端仍会返回)
vaildators 该字段使用的验证器,是一个列表,里面可以定义内置的一些校验规则或自己写校验规则,按照列表的元素顺序进行校验,不管校验有没有通过,都会遍历调用每一个校验器
message:表示未通过校验返回的错误信息
UniqueValidator:验证该字段是否有重复
如:validators=[UniqueValidator(queryset=Projects.objects.all(),message="项目名称不能重复")]
error_messages 自定义错误信息的字典,key为序列化器字段
如:error_messages={"max_length":"负责人长度不能超过50字节","min_length":"负责人长度不能小于10字节"}
其他序列化器字段:
max_length 最大长度
min_length 最小长度
required 是否必填,默认是
trim_whitespace 是否截断空白字符
max_value 最大值(针对int类型)
min_value 最小值(针对int类型)
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息
序列化器类内部定义校验器
单字段校验
a.方法名称必须以validate_作为前缀,后面加上待校验的字段名
b.在内部定义必须把value 返回return出来
def validate_name(self,value):
"""
校验项目名是否以“项目”结尾
:return:
"""
if not value.endswith('项目'):
raise serializers.ValidationError("项目名称必须以项目结尾")
return value
多字段联合校验
需要等单字段校验通过后,才会校验多字段,validate会把前端传过来的参数作字典赋值给attrs
def validate(self, attrs):
name = attrs["name"] leader = attrs["leader"] if "solememory" not in name and "solememory" not in leader: raise serializers.ValidationError("solememory必须在项目负责人或者项目名称中包含") return attrs
字段校验顺序
validators列表条目从左到右进行校验 ---->validate_name通过之后才会对单字段进行校验--->validate 再对多字段进行校验
序列化器类create方法
def create(self, validated_data):
"""
更新项目
:param validated_data: 校验通过之后的项目数据
:return: 项目创建成功之后的模型类对象
"""
project = Projects.objects.create(**validated_data)
return project
project_qs:查询到的模型类对象
当在view视图中调用了serializer .save()方法时,save方法可以传递关键字参数(字典类型),会被create方法中的validated_data接收
在创建序列化器对象时,(这一步的时候:serializer = serializers.ProjectSerializer(data=project_qs)
如果只给data传参,那么使用序列化器对象调用save()方法时,只会调用creat()方法
序列化器类update方法
# instance参数接收的是更新前的参数,validated_data接收的是更新后的参数 def update(self, instance, validated_data): """ :param instance: 待更新的项目模型类对象--->接收的是one_project :param validated_data: 校验通过之后的模型类对象--->接收的是python_data :return: 项目更新成功之后的模型类对象 """ instance.name = validated_data['name'] instance.leader = validated_data['leader'] instance.tester = validated_data['tester'] instance.programmer = validated_data['programmer'] instance.publish_app = validated_data['publish_app'] instance.desc = validated_data['desc'] instance.save() return instance
one_project:数据库查询到的模型类对象
python_data:前端传递过来的参数
在创建序列化器对象时,(这一步的时候:serializer = serializers.ProjectSerializer(instance=one_project, data=python_data)
如果给instance和data同时传递参数,当在view视图中调用了serializer .save()方法时,会自动调用update方法
模型序列化器
因为在序列化器类中又要重新定义模型类中的字段,而且两边的定义相差不大,所以可以定义Meta内部类,设置当前序列化器类的元数据信息
class ProjectModelSerializer(serializers.ModelSerializer): #因为模型序列化器是自动根据模型类生成的,那么我们如果有自定义校验器,可以这样写, 这里自定义的会覆盖掉模型序列化器自动生成的字段,但这里不要轻易指定, 一般模型类没有的字段,可以在这里写,否则最好写在下面的extra_kwargs 中 name = serializers.CharField(label="项目名称", help_text="项目名称", max_length=20, validators=[is_unique_project, cotain_keyword_project]) #如果要定义模型类中没有的字段,可以这样写,但记得添加在下面的fields中 email = serializers.EmailField(label='邮箱', allow_blank=True, allow_null=True, default='keyou@qq.com', read_only=True) # 父表如果需要返回子表中的字段,默认情况下,父表模型序列化器类不会创建子表字段,需要显示创建 # 子表字段名为:子表类名小写_set # 如果子表定义外键字段时,指定了related_name='intfaces',那么这里需要使用related_name使用的值 interfaces_set = serializers.StringRelatedField(many=True) class Meta: # 指定参照哪一个模型类 model = Projects # 指定模型类中的哪些字段来生成序列化器字段,__all__代表所有字段 # 会自动将模型列中的主键添加read_only=True,因为id一般不需要前端传 # fields = '__all__' # 可以在fields中使用元组指定哪些模型类字段需要生成序列化器字段,既需要输入也需要输出 # fields元组中指定的是所有序列化器字段(模型类中不包含的字段也需要在fields中指定) fields=('id', 'name', 'leader', 'tester', 'email ') # 排除模型类字段,这里面的字段不用生成序列化器字段 # exclude = ('create_time', 'update_time', 'desc') # 在read_only_fiels中指定的字段会自动添加read_only=True,可惜没有write_only的方法 # read_only_fiels= ('desc') # 是一个嵌套字典的字典 # 如果只需要改字段中的一部分内容,就没必要重新再像上面一样写一个name,可以在这里指定,以修改的字段名作为key extra_kwargs = { 'name': { 'error_messages': {'max_length': '项目名称的长度不能大于20字节'}, 'read_only': True, 'min_length': 50, 'validators': [is_unique_project, cotain_keyword_project] }, 'leader': { 'label': '负责人', 'write_only': True } } #ModelSerializer内部有creat和update方法,无需自己定义 # 假如email字段设置的是write_only,那么该字段通过校验之后会调用create方法,但是数据库中不存在这个字段,会导致报错,这个时候可以重写create方法 def create(self, validated_data): # 删除emalil后再次调用create方法 email = validated_data.pop('email') super().create(validated_data)
外键表中的模型序列化器
class ProjectModelSerializer(serializers.ModelSerializer): class Meta: model = Projects fields = '__all__' class InterfacesModelSerializer(serializers.ModelSerializer): # 会默认将外键字段project生成PrimaryKeyRelatedField类型,默认返回的是父表对应的id值 # 可以重写默认生成的project,重写改成了StringRelatedField方法,会自动调用父表的__str__方法,输出父表的name # project = serializers.StringRelatedField(label="所属项目") # 使用父表的模型序列化器来创建,就可以获取父表中的一些字段 project = ProjectModelSerializer(read_only=True) class Meta: # 指定参照哪一个模型 model = Interfaces fields = '__all__'
浙公网安备 33010602011771号