在实际开发中,不仅仅是对输入框字符的格式校验,比如注册功能,注册账号还得校验数据库是否已经有账号被注册过了。
有些场景不仅仅是对单个输入框的字符校验,比如修改密码的时候,会涉及2个输入框的数据格式校验,像这些复杂的场景校验需用到校验钩子来实现。
校验form表单数据合法性,is_valid()方法调用顺序:
局部钩子命名规则为clean_字段名称,如:clean_city,clean_years。
super() 重写__init__
,可以批量更新class属性。
# 作者-上海悠悠 QQ交流群:717225969 # blog地址 https://www.cnblogs.com/yoyoketang/ class SubmitPageForm(forms.ModelForm): class Meta: model = Submit # fields = "__all__" #全部字段 fields = ["city", "years", "details"] widgets = { "city": widgets.TextInput(attrs={ "placeholder": "输入城市:北京/上海/深圳" }), "years": widgets.TextInput(attrs={ "placeholder": "输入年限"}), "details": widgets.TextInput(attrs={ "placeholder": "输入详情"}), } labels = { "city": "城 市", "years": "年 限", "details": "详 情", } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 批量更新class属性 for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) def clean_city(self): """局部钩子判断城市必须是北京/上海/深圳其中一个""" city_val = self.cleaned_data.get('city', '') if city_val in ["北京", "上海", "深圳"]: return city_val else: raise forms.ValidationError('城市只能选:北京/上海/深圳')
定义视图
# 作者-上海悠悠 QQ交流群:717225969 # blog地址 https://www.cnblogs.com/yoyoketang/ class SubmitView(View): def get(self, request): form_obj = SubmitPageForm return render(request, "submit.html", locals()) def post(self, request): form_obj = SubmitPageForm(request.POST) if form_obj.is_valid(): # data = form_obj.cleaned_data() form_obj.save() msg = "保存成功" return HttpResponseRedirect('/total') else: # 全局钩子自定义错误提示获取 # print(form_obj.errors.get('__all__')) # error_msg = form_obj.errors.get('__all__') return render(request, "submit.html", locals())
模板内容如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>提交页面</title> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <form role="form" action="" method="POST" id="detail-form" > {% csrf_token %} {% for field in form_obj %} <div class="form-group"> {{ field.label_tag }} {{ field }} <div style="color: red"> {{ field.errors }} </div> </div> {% endfor %} <p> <input type="submit" value="提交" > </p> </form> </div> </body> </html>
输入不合法的内容,会显示field.errors内容
针对单个字段校验可以用局部钩子实现,如果我们要校验多个字段,比如校验注册的时候输入2次密码一致,可以用全局钩子实现。
定义全局钩子使用clean方法
# 作者-上海悠悠 QQ交流群:717225969 # blog地址 https://www.cnblogs.com/yoyoketang/ class SubmitPageForm(forms.ModelForm): class Meta: model = Salary fields = "__all__" #全部字段 # 省略中间代码。。。。。 # 全局钩子 def clean(self): """在通过基础验证的干净数据中get获取字段""" pwd1 = self.cleaned_data.get('password') pwd2 = self.cleaned_data.get('password2') if pwd1 and pwd2: # 这里判断2个字段都是校验通过 if pwd1 == pwd2: # 数据没问题,那么原封不动返回即可 return self.cleaned_data else: # 错误信息储存到 errors {'__all__':[e,]} raise ValidationError('两次密码输入不同') else: return self.cleaned_data
前端可以通过fomr_obj.errors.__all__
获取到内置校验器的全部错误信息