文章目录
一、反序列化数据校验源码分析
反序列化数据校验,
校验顺序为:先校验字段自己的规则(最大、最小),然后是局部钩子,然后是全局钩子
-
反序列化校验开始
在视图类中的s_valid()被执行时,就会进行反序列化的校验,校验通过返回True,否则返回False -
反序列化的过程
- ser.is_valid()是序列化类的对象,假设序列化类是BookSerializer,当执行is_valid时。首先在序列化类产生的对象中查找,当找不到就会去找到它的父类中找,结果在它父类的父类中找到了BaseSerializer
BaseSerializer类
def is_valid(self, *, raise_exception=False):
'断言检查,确保类的实例中具有名为initial_data的属性,如果没有就引发下面这段话包含的特定的错误信息'
assert hasattr(self, 'initial_data'), (
'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
if not hasattr(self, '_validated_data'):
'''
self序列化类的对象,属性中没有_validated_data,就一定会走这句
并且只要走过一次后,下一次就无需再次走了,它优化了is_valid被多次调用,只会走一次校验
'''
try:
'真正的走校验,一旦执行了这里,以后self中就有了_validated_data'
'''
然后我们就得去看看这个self.run_validation(self.initial_data)
我们不能直接按住ctrl键点击,因为它会从当前类中找run_validation,
我们得清楚,这个self是谁,它还是我们的视图类,所以我们得返回到视图类从它一步一步往它继承的类中找
清楚如何查找后,我们就从视图类----》serializer.Serializer(找到了,为什么从这个里面找因为
我们就是使用serializer.Serializer类的)
'''
self._validated_data = self.run_validation(self.initial_data)
'''
这下面的是当校验不通过时,执行的,会给_validatad_data设置为一个空字段,
并且给_errors设置为验证错误的详细信息
'''
except ValidationError as exc:
self._validated_data = {
}
self._errors = exc.detail
else:
self._errors = {
}
return not bool(self._errors)
通过上面self.run_validation(self.initial_data)我们找到了下面这块源码,
而这里的run_validatiion方法就是DRF序列化器验证过程中的核心
def run_validation(self, data=empty):
'''
局部钩子的执行,这里的self就还是视图类的对象
data就是前端传入的数据,value是前端传入,字段自己校验通过的字典
'''
value = self.to_internal_value(data)
try:
'这个是字段验证器'
self.run_validators(value)
'''
这个是全局钩子的执行,和上面一样self是视图类的对象,如果我们在序列化其中写了全局钩子,
那么就优先使用我们自己定义的全局钩子,如果没写则执行父类的,(serializer.Serializer)
结果可以看到父类根本就没有做校验
def validate(self, attrs):
return attrs
'''
value = self.validate(value) #运行自定义验证方法
'确保自定义验证方法返回了验证后的数据'
assert value is not None, '.validate() should return the validated data'
except (ValidationError, DjangoValidationError) as exc:
# 捕获验证过程中可能引发的异常,并转换为DRF的ValidationError
raise ValidationError(detail=as_serializer_error(exc))
# 返回验证后的数据
return value
看完了全局钩子后我们在看一下局部钩子的self.to_internal_value(data),也是一样的思路,从视图类找,
视图类肯定没有,然后找父类serializer结果就是这个页面的
def to_internal_value(self, data):
ret = OrderedDict()# 用于存储验证后的数据
errors = OrderedDict()# 用于存储字段验证过程中的错误信息
fields = self._writable_fields# 获取序列化器中的所有字段
'序列化类中所有的字段,for循环每次取一个字段对象。例如name=CharField()'
for field in fields:
'''去视图类的对象中反射,validate_字段名的方法,如果有就执行,没有就不执行'''
validate_method = getattr(self, 'validate_' + field.field_name, None)
primitive_value = field.get_value(data)
try:
'这句话就是字段自己的校验规则(最长最短长度等)'
validated_value

本文详细剖析了DRF中的反序列化数据校验流程,包括字段验证规则、局部钩子和全局钩子的执行,以及Request和Response类在处理不同数据格式时的作用。同时介绍了如何在DRF视图中配置解析器和渲染器。
最低0.47元/天 解锁文章
429

被折叠的 条评论
为什么被折叠?



