drf--序列化+断言assert

9.27内容整理和概述

今日内容概要

内容目录

  • drf序列化类常用字段类
  • drf序列化类常用字段参数
  • 序列化类之source参数
  • 序列化类之定制序列化字段
  • ModelSerializer序列化
  • 反序列化之数据校验
  • 断言assert

drf序列化类常用字段类

高频率:
	1.CharField:字符类型	# 例子:变量 = serializers.CharField()
	2.IntegerField:整数类型		# 例子:变量 = serializers.IntegerField()
	3.1 FloatField:浮点数类型		# 例子:变量 = serializers.FloatField()
	3.2 DecimalField:浮点数类型		# 例子:变量 = serializers.DecimalField()
	4.ListField:列表类型	
	5.DictField:字典类型
    
普通频率:
	1.BooleanField:布尔类型		# 例子:变量 = serializers.BooleanField()
	2.NullBooleanField:布尔类型(可以为空)		# 例子:变量 = serializers.NullBooleanField()
	3.EmailField:存放邮箱		# 例子:变量 = serializers.EmailField()
	4.1 RegexField:存放正则		# 例子:变量 = serializers.RegexField()
	4.2 SlugField:存放正则		# 例子:变量 = serializers.SlugField()
	5. URLField:存放url地址		# 例子:变量 = serializers.URLField()
	6.UUIDField:存放特殊类型字符串(例子:5ce0e9a5-5ffa-654b-cee0)	# 没用过,没有栗子举
	7.IPAddressField:存放ip地址		# 有非常规参数
	8.1 DateTimeField:时间类型		# 有非常规参数
	8.2 DateField:时间类型		# 有非常规参数
	8.3 TimeField:时间类型		# 有非常规参数
	8.4 DurationField:时间类型
	9.1 ChoiceField:单选
	9.2 MultipleChoiceField:多选
	10.FileField:文件类型		# 例子:变量 = FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
	11.ImageField:图片类型		# 例子:变量 = serializers.ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

drf序列化类常用字段参数

功能:用于反序列化校验参数

选项参数:		# 指定类的专属参数
	1.CharField类参数:
		1.max_length:最大长度
		2.min_lenght:最小长度
		3.allow_blank:是否允许为空
		4.trim_whitespace:是否截断空白字符
	2.IntegerField类参数:
		1.max_value:最小值
		2.min_value:最大值

通用参数:
	1.required:表明该字段在反序列化时必须输入(必填)		# 默认True
	2.default:反序列化时使用的默认值
	3.allow_null:表明该字段是否允许传入None	# 默认False
	4.validators:该字段使用的验证器(第二层校验)		# 不需要了解,也不需要用
	5.error_messages:包含错误编号与错误信息	# 字典类型
	6.label:用于HTML展示API页面时,显示的字段名称 		# 不重要
	7.help_text:用于HTML展示API页面时,显示的字段帮助提示信息		# 不重要
	'------重点------'
	8.read_only:表明该字段仅用于序列化输出		# 默认False
	9.write_only:表明该字段仅用于反序列化输入		# 默认False

序列化类之source参数

功能:绑定序列化类字段与model类字段的对应关系,从而实现改字段名操作
	例子:book_name = serializers.CharField(max_length=8, min_length=3,source='name')
	功能:绑定book类的name字段,并且发送数据时字段名为book_name
	# 补充:source参数名不能和该字段名相同,不然报错

source参数范围:
	1.model类字段
	2.model类方法
	3.可以通过对象进行跨表绑定	# 例子:source='对象.字段'

序列化类之定制序列化字段

'--------------第一种---------------'
基于SerializerMethodField方法定制:		# 例子:字段名 = serializers.SerializerMethodField()
	前提:必须配合一个'get_字段名'的方法,且有参数(self,obj)	# obj:当前被序列化的对象
	功能:此方法返回什么该字段便是什么数据
	例子:
		class BookSerializer(serializers.Serializer):		# 当前路径:serializer.py
			publish = serializers.SerializerMethodField()
			def get_publish(self, obj):
				return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email}

'--------------第二种---------------'
基于model表模型方法定制:			# 架构师:领域驱动模型(ddd)
	原理:类似序列化model表字段去序列化model表方法
	步骤:
		1.先在models表中定义方法,规定返回的数据
		2.在serializer表中,直接序列此方法
	例子:
		class Book(models.Model):
            def publish_detail(self):		# 当前路径:models.py
                return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}
            
		publish_detail=serializers.DictField()		# # 当前路径:serializer.py

ModelSerializer序列化

应用背景:传统的serializers.Serializer类做数据的序列化,太过冗长,为了简便效率,用Serializer的子类:ModelSerializer

Serializer的缺点:
	1.无论是序列化还是反序列化,每个字段都要写
	2.如果新增或者修改,在序列化类中都需要重写create或update
    
步骤:
	1.定义一个序列化类继承serializers.ModelSerializer
	2.类内部写必须写内部类Meta类
	3.在内部类中指定model(要序列化的表)		# 例子:model = Book 
	4.在内部类中指定fields		# fields属性指定序列化和反序列化的字段
	5.在extra_kwargs参数中添加字段参数
	6.支持在ModelSerializer优先使用重写字段
	7.不需要重写create和update	# 也可以重写,如果重写优先使用自己重写的

例子:
	class BookModelSerializer(serializers.ModelSerializer):
		 name = serializers.SerializerMethodField()		# 重写字段
			def get_name(self, obj):
				return 'sb---' + obj.name
            
		class Meta:		# Meta类必写
            model = Book  # model属性指定被序列化的表模型
            fields = ['name', 'price', 'publish_date', 'publish', 'authors', 'publish_detail',
                      'author_list']   # fields属性指定序列化和反序列化的字段。当fields='__all__'时,指所有字段都序列化
            extra_kwargs = {		# extra_kwargs给字段增加参数
                'name': {'max_length': 8},
                'publish': {'write_only': True},
                'authors': {'write_only': True},
            }  
'--------------基于SerializerMethodField方法定制字段做反序列化---------------'
       publish_detail = serializers.SerializerMethodField(read_only=True)	# 
         ...
       author_list = serializers.SerializerMethodField(read_only=True)
        ...
'--------------基于基于model表模型方法字段做反序列化---------------'
	直接将model表的方法字段名写在fields参数里

反序列化之数据校验

三层数据校验:
	第一层————字段的校验规则
    
	第二层————局部钩子校验:		# Serializer类和ModelSerializer类写法一样
		步骤:
            1.定义'validate_字段名'方法
            2.方法参数为(self, 字段)
            3.编写校验逻辑
            4.校验不通过,抛异常		# ValidationError
            5.校验通过将字段返回出去
        例子:
            def validate_name(self, name):
                if name.startswith('sb'):
                    raise ValidationError('不能以sb卡头')
                else:
                    return name
	
	第三层————全局钩子校验:
		步骤:
 			1.定义'validate'方法
			2.方法参数为(self, 全部数据)
			3.编写校验逻辑
			4.校验不通过,抛异常		# ValidationError
			5.校验通过将全部数据返回出去
		例子:
			def validate(self, attrs):
				if attrs.get('name') == attrs.get('publish_date'):
					raise ValidationError('名字不能等于日期')
				else:
					return attrs

执行顺序:字段的校验规则-->局部钩子校验-->全局钩子校验		# 顺序:一二三

'------------源码分析---------------'
	1.视图类中检验数据调用'数据对象.is_valid()'
	2.is_valid方法在BaseSerializer类中,真正的作用就是调用Serializer类中的run_validation方法
		# 源码:self._validated_data = self.run_validation(self.initial_data)
	3.run_validation方法主要功能:
		1.执行to_internal_value方法,进行字段检验和局部钩子		# 源码:value = self.to_internal_value(data)
		2.当两者都通过时,执行全局钩子	# 源码:value = self.validate(value)
	4.to_internal_value方法主要步骤:
		1.循环序列化类中所有的字段		# 源码:for field in fields:
		2.每次循环通过反射拿取局部钩子的地址		# 源码:validate_method = getattr(self, 'validate_' + field.field_name, None)
		3.然后进行字段检验		# 源码:validated_value = field.run_validation(primitive_value)
		4.如果局部钩子存在,进行局部钩子检验		# 源码:if validate_method is not None: validated_value = validate_method(validated_value)
		5.如果字段检验不合格,第一次循环就立即结束报错,所以检验执行顺序:字段的校验规则-->局部钩子校验


补充:自己写的序列化类---》继承了ModelSerializer---》继承了Serializer---》BaseSerializer---》Field

断言assert

功能:断定一个变量必须是xx,如果不是就报错

例子:
	name = 'lqz1'
	assert name == 'lqz', 'name不等于lqz'		
	print('程序执行完了')

解释:
	1.如果name为lqz,执行下面的程序
	2.如果name不为lqz,抛异常,报错信息为'name不等于lqz'	
posted @ 2023-04-17 23:40  维生素Z  阅读(6)  评论(0)    收藏  举报