一、机制流程:
1、后端接收请求数据。
2、后端校验数据并封装校验结果发送给前端。
3、前端根据数据校验结果渲染页面/展示提示信息。
4、forms组件只会自动渲染获取用户输入的标签(input select radio checkbox)。
二、前端校验与后端校验
1、前端校验:可靠性比较低,可用可无。
2、后端校验:比较可靠,必须要有。
三、需要导入的模块
from django import forms from django.core.validators import RegexValidator # 正则检验相关
四、实例:
1、views.py -- class:
class FormDemon(forms.Form): username = forms.CharField( min_length=3, # 限制①,长度不得小于3 max_length=8, # 限制②,长度不得大于8 label='用户名:', # 设置贴签的内容,若不设置,则就用字段名 initial='tom', # 设置默认值 error_messages={ # 设置对应限制不满足时的提示信息,若不设置,则用默认提示样式 'min_length': '用户名长度不得小于3位', 'max_length': '用户名长度不得大于8位', 'required': '用户名不得为空' # 默认限制,非空 }, # 设置<text>形式<input>标签的属性 widget=forms.widgets.TextInput( attrs={'class': 'form-control other_class'} ) ) password = forms.CharField( min_length=3, max_length=8, label='密码:', error_messages={ 'min_length': '密码长度不得小于3位', 'max_length': '密码长度不得大于8位', 'required': '密码不得为空' }, # 设置<password>形式<input>标签的属性 widget=forms.widgets.PasswordInput( attrs={'class': 'form-control'} ) ) re_password = forms.CharField( min_length=3, max_length=8, label='确认密码:', error_messages={ 'min_length': '密码长度不得小于3位', 'max_length': '密码长度不得大于8位', 'required': '密码不得为空' }, widget=forms.widgets.PasswordInput( attrs={'class': 'form-control'} ) ) email = forms.EmailField( label='邮箱(选填):', required=False, # 设置为可为空 error_messages={ 'invalid': '邮箱格式不正确' # 邮箱字段的默认限制,必须符合邮箱格式 }, # 设置<email>形式<input>标签的属性 widget=forms.widgets.EmailInput( attrs={'class': 'form-control'} ) ) phone = forms.CharField( label='手机号(选填):', required=False, validators=[ # 验证手机号的正则匹配式 # 限定11位,限定1开头,第二位只能是[3,5,6,8,9]中的一个,后9位任意数字 RegexValidator(r'^[1][3,5,6,8,9][0-9]{9}$', '请输入正确的手机号') ], widget=forms.widgets.TextInput( attrs={'class': 'form-control'} ) ) gender = forms.ChoiceField( choices=( (1, '男'), (2, '女'), (3, '未知') ), label='性别:', initial=3, # 设置<radio>形式<select>标签的属性 widget=forms.widgets.RadioSelect() ) hobby = forms.ChoiceField( choices=( (0, '请选择(不选)'), (1, '旅游'), (2, '电子游戏'), (3, '太极拳'), ), initial=0, label='爱好(选填):', # 设置单选<select>标签的属性 widget=forms.widgets.Select() ) skill = forms.MultipleChoiceField( choices=( (0, '请选择(不选)'), (1, '倒立俯卧撑'), (2, '三口一头猪'), (3, '人体描边术'), ), initial=[0, ], label='特技(选填/可多选):', # 设置多选<select>标签的属性 widget=forms.widgets.SelectMultiple() ) # direct_login = forms.ChoiceField( # label='是否直接登录:', # initial='checked', # # required=False, # # 设置单选<checkbox>标签的属性 # widget=forms.widgets.CheckboxInput() # ) channel = forms.MultipleChoiceField( choices=( (0, '请选择(不选)'), (1, '体育'), (2, '动漫'), (3, '老司机'), ), initial=[0, ], required=False, label='感兴趣的频道(选填/可多选):', # 设置多选<checkbox>标签的属性 widget=forms.widgets.CheckboxSelectMultiple() )
2、views.py --- def:
def use_form(request): form_obj = FormDemon() # 先生成一个同名的空的form对象用于初始页面 if request.method == 'POST': form_obj = FormDemon(request.POST) # 将 request.POST 中的键值对都放入form对象中进行校验 # 校验准则1:类中定义的字段,除非声明可以为空,否则都需要有值,有错或不全都无法全体合法 # 校验准则2:多传的未定义的字段会被直接忽略,所以不会被标记为非法,也不会被标记为合法 if form_obj.is_valid(): # 是否全体合法 return HttpResponse('信息已上传') print('以下是合法部分:') print(form_obj.cleaned_data) print('以下是非法部分:') print(form_obj.errors) return render(request, 'form_page.html', locals())
3、templates:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {% load static %} <script src="{% static 'jQuery351.js' %}"></script> <link rel="stylesheet" href="{% static 'Bootstrap337/css/bootstrap.min.css' %}"> <script src="{% static 'Bootstrap337/js/bootstrap.min.js' %}"></script> </head> <body> <div class="container"> <p><h1>注册信息</h1></p> <form action="" method="post" novalidate> <!--novalidate(取消浏览器校验)--> {# <!--第一种渲染方式,代码很少,封装度高,扩展性差-->#} {# {{ form_obj.as_p }}#} {# {{ form_obj.as_ul }}#} {# {{ form_obj.as_table }}#} {# <!--第二种渲染方式,代码较多,扩展性强-->#} {# <p>{{ form_obj.username.label }}{{ form_obj.username }}</p>#} {# <p>{{ form_obj.password.label }}{{ form_obj.password }}</p>#} {# <p>{{ form_obj.re_password.label }}{{ form_obj.re_password }}</p>#} {# ...#} <!--第三种渲染方式,代码精简,扩展性强--> {% for member in form_obj %} <p>{{ member.label }}{{ member }}</p> <p style="color: red">{{ member.errors.0 }}</p> <!--调整提示信息样式--> {% endfor %} <input type="submit" class="btn btn-info" value="提交信息"> </form> </div> </body> </html>
五、钩子函数:
1、钩子函数在Forms组件中相当于于再次校验,可以自定义校验规则。
2、分类:
①局部钩子:只能拿出某一个字段进行额外的校验。
②全局钩子:可以拿出所有的字段进行任选多个进行额外的校验。
3、钩子函数在类里面自定。
4、实例:
# 局部钩子,指定某一个字段 def clean_username(self): username_again = self.cleaned_data.get('username') # 已通过第一次校验的才会进行再次校验 if '4' in username_again: # 自定义限制 self.add_error('username', '用户名包含敏感数字') # 编辑提示信息 return username_again # 编辑完放回该字段 # 全局钩子,可用于所有字段 def clean(self): password_again = self.cleaned_data.get('password') re_password_again = self.cleaned_data.get('re_password') if password_again != re_password_again: self.add_error('re_password', '两次输入的密码不一致') return password_again, re_password_again # 编辑完放回拿出的字段,或直接放回全部字段