Python Day19 forms组件钩子

forms组件钩子

局部钩子

对字段校验有特殊的需求,此时可以使用局部钩子来增加校验内容
下面的例子中判断前端页面传过来的user是否是以yuan开头的字符串

示例代码
点击is_valid,引入ValidationError

from django.core.exceptions import ValidationError
class UserForm(forms.Form):

    user = forms.CharField(
        label="用户名",  #自定义form表单显示到网页的名字
        min_length=5,
        error_messages={"required": "不能为空", "min_length": "最小长度不能小于5"},  #自定义错误提示信息
        widget=widgets.TextInput(attrs={"class": "form-control"})  #自定义属性,添加一个Bootstrap样式
    )

    def clean_user(self): #clean_是固定写法
        val = self.cleaned_data.get("user") #cleaned_data里面是经过form组件默认规则校验后的内容
        if val.startswith("yuan"): #如果校验通过则返回原值
            return val
        else: #如果校验未通过则抛错
            raise ValidationError("用户名必须以yuan开头")

解析源码
由于最终校验是使用is_valid方法,那么我们看看is_valid方法里面有什么

def is_valid(self):
    """
    Returns True if the form has no errors. Otherwise, False. If errors are
    being ignored, returns False.
    """
    return self.is_bound and not self.errors #只有self.errors为空是才返回True
@property
def errors(self):
    "Returns an ErrorDict for the data provided for the form"
    if self._errors is None: #第一次运行当然为None
        self.full_clean() #去看看full_clean执行了什么
    return self._errors
def full_clean(self):
    ...
    self._clean_fields() #校验字段,这就是局部钩子关键所在,进去看看
    self._clean_form()

_clean_fields中将校验字段及规则做循环

def _clean_fields(self):
    for name, field in self.fields.items(): #self.fields就是需要校验的字段,{"user":user字段的规则对象}
        ...
        try:
            ...
            else:
                value = field.clean(value) #判断是否符合校验规则,不符合直接抛错,符合则继续往下走
            self.cleaned_data[name] = value #如果校验成功则存入cleaned_data字典
            if hasattr(self, 'clean_%s' % name): #钩子来源于这里,通过反射查询当前类下有没有一个叫'clean_%s' % name的方法
                value = getattr(self, 'clean_%s' % name)() #执行这个方法,返回值交给value
                self.cleaned_data[name] = value
        except ValidationError as e:
            self.add_error(name, e) #如果报错,则将字段名和错误信息组成键值对放入到errors字典中去

全局钩子

校验的规则涉及到多个字段值
比如:判断两次密码是否一致
全局错误在errors中的键值为"all"
通过form.errors["all"][0]来获取

示例代码
举例判断用户名和电话是否一致

def clean(self): #函数名是固定写法
    user = self.cleaned_data.get("user")
    tel = self.cleaned_data.get("tel")
    if user == tel:
        return self.cleaned_data #如果验证成功的固定写法
    else:
        raise ValidationError("用户名与电话不同")

源码解析

def full_clean(self):
    ...
    self._clean_fields() 
    self._clean_form() #全局钩子
def _clean_form(self):
    try:
        cleaned_data = self.clean() #执行clean方法
    except ValidationError as e: #如果报错同样可以捕获到
        self.add_error(None, e) #做全局校验没有具体的字段,这个键值叫做'__all__'
    else:
        if cleaned_data is not None:
            self.cleaned_data = cleaned_data
def clean(self):
    """
    Hook for doing any extra form-wide cleaning after Field.clean() has been
    called on every field. Any ValidationError raised by this method will
    not be associated with a particular field; it will have a special-case
    association with the field named '__all__'.
    """
    return self.cleaned_data #自己定义的clean也要返回self.cleaned_data

这个clean就是留给我们的接口,我们自己写一个clean就不需要走这里了
全局错误都在form.errors["all"][0]中

转载于:https://blog.51cto.com/dzm911/2116325

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值