django表单form的is_valid源码分析


一、is_valid的作用

验证表单数据是否正确,如果正确返回True,否则False

二、is_valid的验证流程

  1. 首先验证is_bound和errors,意思为如果表单有数据,且无错误,则返回True,否则 False.
  2. 我们分析self.errors方法,此方法返回一个错误字典,里面包含所有填入表单的错误信息,例如:少填了字段错误, 字段超长,值的格式不符等等。类似 {‘username’:[‘This field is required’], ‘sender’:[‘Enter a valid Email Adress.’] }
  3. 接下来是full_clean方法,作用是"清洗"表单中的数据,并把正确的数据放入self.cleaned_data字典,错误的放放self._errors中,具体实现是4,5,6三个方法
  4. self._clean_fields(),循环验证(field.clean方法验证)每个字段中的数据是否是合法的。我们可以看到在每一次循环的最后还设置了hook钩子,clean_字段(如果有的话!)来验证,所以你可以subclass来扩展自己的钩子函数
  5. self._clean_form(),这个方法实际上是调用self.clean钩子函数
  6. self._post_clean(),这个也是钩子函数
    验证完成!

三、源码带注释

    def is_valid(self):
        """Return True if the form has no errors, or False otherwise.
			如果表单没有错误返回True,否则返回False
		"""
		# self.is_bound = data if data is not None or files is not None
		#is_bound 只要前端往表单中填入了数据,is_bound就是True
		#self.errors 只要self.errors中有值,那么not self.errors返回False,否则True
        return self.is_bound and not self.errors
       
  	@property
    def errors(self):
        """Return an ErrorDict for the data provided for the form.
			如果填入表单中的值有错误,则返回一个错误字典
		"""
        if self._errors is None:
            self.full_clean()
        return self._errors
        
    def full_clean(self):
        """
        Clean all of self.data and populate self._errors and self.cleaned_data.
        清洗填入表单中的数据,并把有错误的放入到self._errors字典中,合法的放入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:
           	   # 如果字段是disabled禁用状态,则获取该字段的初始化的值
               value = self.get_initial_for_field(field, name)
           else:
           		# 否则获取该字段的的值,并赋值给value变量
               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:
               		#这里是真正的验证字段的方法field.clean!!!,具体根据validators验证器规则来验证,还可以添加自己的验证器!具体为自己写个验证函数,然后将其放入到字段类的validators变量中。类似even_field = models.IntegerField(validators=[validate_even])
                   value = field.clean(value)
               self.cleaned_data[name] = value
               #每用field.clean验证完后,再寻找用户自定义的clean_字段的钩子函数继续验证!!
               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)

四、一个自定义的hook钩子

class LoginForm(forms.Form):
    Email = forms.EmailField(max_length=100)
	# 如果填入的邮箱不是以@qq.com结尾的则报错
    def clean_Email(self):
        if not self.cleaned_data['username'].endswith('@qq.com'):
            raise ValidationError('email address must be ends with @qq.com')
        else:
            return self.cleaned_data['Email']

五、总结

is_valid的验证顺序为:self._clean_fields(每验证完一个字段,再执行用户的clean_字段方法,如果有的话) --> self._clean_form --> self._post_clean

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你抱着的是只熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值