Django学习——forms组件源码分析

1 forms组件源码分析

1 为什么局部钩子要写成clean_字段名,为什么要抛异常
2 入口在is_valid()
3 校验流程
	-先校验字段自己的规则(最大,最小,是否必填,是不是合法)
	-校验局部钩子函数
	-全局钩子校验
    
4 流程
	-is_valid()  --> return self.is_bound and not self.errors
	-self.errors: 方法包装成了数据属性
        -一旦有值,self.errors就不进行校验(之前调用过了)
	- self.full_clean():  核心
        
 if not self.is_bound:  # Stop further processing. 如果data没有值直接返回
    return

    def full_clean(self):
        """
        Clean all of self.data and populate self._errors and self.cleaned_data.
        """
        self._errors = ErrorDict()
        if not self.is_bound:  # Stop further processing.
            return
        self.cleaned_data = {}
        # If the form is permitted to be empty, and none of the form data has
        # changed from the initial data, short circuit any validation.
        if self.empty_permitted and not self.has_changed():
            return

        self._clean_fields()
        self._clean_form()
        self._post_clean()
        
     # 局部钩子执行位置  
    def _clean_fields(self):
        for name, field in self.fields.items():
            # value_from_datadict() gets the data from the data dictionaries.
            # Each widget type knows how to retrieve its own data, because some
            # widgets split data over several HTML fields.
            if field.disabled:
                value = self.get_initial_for_field(field, name)
            else:
                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
            try:
                if isinstance(field, FileField):
                    initial = self.get_initial_for_field(field, name)
                    value = field.clean(value, initial)
                else:
                    value = field.clean(value)  # 字段自己的校验规则
                self.cleaned_data[name] = value  # 把校验后的数据放到cleaned_data
                if hasattr(self, 'clean_%s' % name):  # 判断有没有局部钩子
                    value = getattr(self, 'clean_%s' % name)() # 执行局部钩子
                    self.cleaned_data[name] = value  # 校验通过 把数据替换一下
            except ValidationError as e:  # 如果校验不通过,会抛异常,会被捕获
                self.add_error(name, e)  # 捕获后执行  添加到错误信息 errors是个列表 错误可能有多个
                
      
# 全局钩子执行位置
    def _clean_form(self):
        try:
            # 如果自己定义的form类中写了clean,他就会执行
            cleaned_data = self.clean()  
        except ValidationError as e:
            self.add_error(None, e) # key作为None就是__all__
        else:
            if cleaned_data is not None:
                self.cleaned_data = cleaned_data
posted @ 2022-05-12 23:18  寻月隐君  阅读(45)  评论(0编辑  收藏  举报