|
[forms组件源码]
切记一个一个看,大致弄懂什么逻辑,可以复用出来即可以
分析源码流程
1、后端的form.is_valid()是入口
def is_valid(self):
return self.is_bound and not self.errors[self代表form自己写的对象]
self.is_bound 看了源码,只要有数据或者有字段就为True
not self.errors 可以推出self.error为false在通过not取反那么 is_valid则全部合法
2、self.error
@property[将方法伪装为属性]
def errors(self):
if self._errors is None:[源码看到self._errors是空的会走这里面判断]
self.full_clean()
return self._errors
3、self.full_clean()
def full_clean(self):
self._errors = ErrorDict()[定义一个空的错误信息字典]
if not self.is_bound: [只要有数据就不会走这一步]
return
self.cleaned_data = {}[定义一个清洗过的容器]
...
self._clean_fields()[局部校验,内部是for循环先进行字段自己的规则校验,在进行局部钩子的校验]
if hasattr(self, 'clean_%s' % name): # 利用反射获取局部钩子函数
value = getattr(self, 'clean_%s' % name)()#getattr获取属性的值加括号调用有一个结果接收,如果不传回去,那么下面的cleaned_data就取不出来数据
self.cleaned_data[name] = value # 钩子运行的结果和字段也存放到clean_data里面中去,如果没有value就没有数据
self._clean_form()[局部校验完成后走,全局校验、然后里面的之前定义的cleaned_date的值和_error的值就会由空变得有值]
def _clean_form(self):
try:
cleaned_data = self.clean()[form的全局钩子校验,自己写的返回一个self.cleaned_date]
except ValidationError as e:
self.add_error(None,e)[如果报错就添加到errors中去]
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data
self._post_clean()
[内部钩子通常不用的,拓展性变强,后期可以在往里面做额外的校验-
[总结]
首先通过后端产生一个form对象,然后form.is_valid()是一个入口--->看到父类的self.errors中的父类的full_clean--->看到有定义error、cleaned_date空字典
--->核心业务逻辑①self._clean_fields()内部for循环先校验每个对象的本身的字段的配置规则,校验完成后在走局部钩子--->self._clean_fields()每个字段校验完成在走全部钩子
--->self就会有clean_data和errors就会有值了
|
|
|