目录
渲染方式一、使用获取的myform对象进行属性获取 - 灵活性最高
渲染方式二、 对获取的myform对象进行循环取值 - 建议使用
渲染方式三、使用源码内提供属性as_p、as_ul -- (不推荐使用)
2-3 常用选择属性 - radio、select、checkbox
一、数据校验功能
总结:
- form对象.is_valid() -- 返回true表示数据校验通过
- form对象.errors -- 继承于字典,保存了所有错误信息 - {‘name’:[错误信息1,错误信息2,]}
- 字段.errors -- 每个字段的错误信息列表
导入模块 - from django import forms
写类继承 forms.Form
注意:
- 内部属性名必须和前端的name一一对应
- 若前端form内的存在name字段在类中不存在,则跳过校验
- 若后台类内的属性在前端内未定义,则校验失败from django import forms class MyForm(forms.Form): # 定义属性,可以用来检验字符串类型 # 限制最大长度是8,最小长度是3 name = forms.CharField(max_length = 8,min_length = 3) # required -- 默认为True,表示是否必填 pwd = forms.CharField(max_length = 8,min_length = 3,required=True) # 校验是否是邮箱格式 email = forms.EmailField()
在函数内实例化上述类对象
注意:
- 若前台使用ajax而不是form传值,则将传过来的字典类型数据扔给myform = MyForm()def index_form(request): if request.method =='GET': return render(request,'index.html') # 生成实例化对象,需要传入要校验的数据(字典) # dic = {'name':'n1','pwd':'123','email':'111',} # myform = MyForm(dic) myform = MyForm(request.POST) # is_valid()方法用于返回是否校验成功 if myform.is_valid(): # cleaned_data属性表示校验通过的数据 -- 本质是字典 print(myform.cleaned_data) return HttpResponse('校验成功') else: # errors属性表示错误的信息 -- 本质是一个字典(ErrorDict) print(myform.errors) print(myform.errors.as_data()) # errors对象内 as_data()方法返回错误信息内容 {'name':[V…Error(['……',])]} return HttpResponse('校验失败')
前端使用form表单提交数据
注意:前端form内的存在name字段,可以在在类中不被定义;但是类中被定义的属性,前端必须有对于name字段<form action="" method="post"> <p>用户名: <input type="text" name="name"></p> <p>密码: <input type="text" name="pwd"></p> <p>确认密码: <input type="text" name="re_pwd"></p> <p>邮箱: <input type="text" name="email"></p> <input type="submit" value="提交"> </form>
1-1 自定义局部校验功能(局部钩子) - 单个属性校验
- myForm类内定义函数 : clean_类内属性名
- 函数内部使用 self.cleaned_data.get('字段名') 取出字段进行校验规则书写
- 错误抛出 ValidationError('错误信息') -- 需要导入相应模块
- 校验完成,函数返回被校验字段
- !!!!注意!!!!:自定义局部钩子函数命名规则:clean_类内对应字段名
from django import forms from django.core.exceptions import ValidationError class MyForm(forms.Form): name = forms.CharField(max_length = 8,min_length = 3) pwd = forms.CharField(max_length = 8,min_length = 3,required=True) email = forms.EmailField() # 针对class内name属性的校验规则,完成了默认规则校验之后的自定义校验 def clean_name(self): # self:当前form对象 name = self.cleaned_data.get('name') if name.startswith('sb'): # 失败,抛异常 raise ValidationError('不能以sb开头') # 正常,把name返回 return name
1-2 自定义全局校验功能(全局钩子) - 多个属性校验
- myForm类内重写clean方法
- 函数内部使用 self.cleaned_data.get('字段名') 取出字段进行校验规则书写
- 错误抛出 ValidationError('错误信息') -- 需要导入相应模块
- 校验完成,函数返回cleanned_data
- !!!!注意!!!!:自定义全局钩子函数必须以clean命名,即重写clean方法!
from django import forms from django.core.exceptions import ValidationError class MyForm(forms.Form): name = forms.CharField(max_length = 8,min_length = 3) pwd = forms.CharField(max_length = 8,min_length = 3,required=True) re_pwd = forms.CharField(max_length = 8,min_length = 3,required=True) email = forms.EmailField() # 针对class内name属性的校验规则,完成了默认规则校验之后的自定义校验 def clean_name(self): # self:当前form对象 name = self.cleaned_data.get('name') if name.startswith('sb'): # 失败,抛异常 raise ValidationError('不能以sb开头') # 正常,把name返回 return name # 针对全局数据的校验规则,单独self.cleaned_data.get('')获取对象值进行规则书写 # 只有通过了默认规则的校验和单个校验后进行全局校验 def clean(self): pwd=self.cleaned_data.get('pwd') re_pwd=self.cleaned_data.get('re_pwd') if pwd==re_pwd: # 返回 self.cleaned_data - 校验通过的数据 return self.cleaned_data else: raise ValidationError('两次密码不一致')
二、模板渲染功能 - 三种方式
- 在视图层实例化对象 myform=MyForm() -- 传输内容表示需要校验的数据,若只渲染无需填入
- 通过 render 将实例化对象内的属性返回给需要渲染的页面
# 渲染模板 def index_form(request): # 生成对象时(实例化),需要传入要校验的数据(字典) myform=MyForm() if request.method=='GET': return render(request,'indxe2.html',locals())
- 前端进行渲染操作
渲染方式一、使用获取的myform对象进行属性获取 - 灵活性最高
<form action="" method="post" > <p>用户名: {{ myform.name }}</p> <p>密码: {{ myform.pwd }}</p> <p>邮箱: {{ myform.email }}</p> <input type="submit" value="提交"> </form>
渲染方式二、 对获取的myform对象进行循环取值 - 建议使用
注意:
- foo.label 属性表示类内属性的标签名,可在class内进行定义
- foo 对象会自动在页面上呈现为一个input输入框,即是在class内定义的属性类型
- 若想要修改foo对象在页面的显示样式(例如css样式或pwd隐藏),需要使用widget参数进行配置,详见2-2
<form action="" method="post" > {% for foo in myform %} <p>{{ foo.label }}:{{ foo }}</p> {% endfor %} <input type="submit" value="提交"> </form>
from django import forms class MyForm(forms.Form): name = forms.CharField( max_length=8, min_length=3, label='用户名',) pwd = forms.CharField(max_length=8, min_length=3, required=True, label='密码',) re_pwd = forms.CharField(max_length=8, min_length=3, required=True, label='确认密码',) email = forms.EmailField(label='邮箱',)
渲染方式三、使用源码内提供属性as_p、as_ul -- (不推荐使用)
<form action="" method="post" > {{ myform.as_p }} <hr> {{ myform.as_ul }} <input type="submit" value="提交"> </form>
2-1 Django类创建 - 内置字段
Field required=True 是否允许为空 widget=None HTML插件 label=None 用于生成Label标签或显示内容 initial=None 初始值 help_text=' 帮助信息(在标签旁边显示) error_messages=None 错误信息 {'required': '不能为空', 'invalid': '格式错误'} show_hidden_initial=False 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) validators=[] 自定义验证规则 localize=False 是否支持本地化(根据不同语言地区访问用户显示不同语言) disabled=False 是否可以编辑 label_suffix=None abel内容后缀 CharField(Field) max_length=None 最大长度 min_length=None 最小长度 strip=True 是否移除用户输入空白 IntegerField(Field) max_value=None 最大值 min_value=None 最小值 DecimalField(IntegerField) 小数,举例,涉及金钱计算保留小数点后两位小数,举例,涉及金钱计算保留小数点后两位 max_value=None 最大值 min_value=None 最小值 max_digits=None 总长度 decimal_places=None 小数位长度 BaseTemporalField(Field) input_formats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField) 格式:2015-09-01 11:12 DurationField(Field) 时间间隔:%d %H:%M:%S.%f RegexField(CharField) regex 自定制正则表达式 max_length=None 最大长度 min_length=None 最小长度 error_message=None 忽略,错误信息使用 error_messages={'invalid': '...'} FileField(Field) allow_empty_file=False 是否允许空文件 ImageField(FileField) 需要PIL模块,pip3 install Pillow ChoiceField(Field) choices=() 选项,如:choices = ((0,'上海'),(1,'北京'),) required=True 是否必填 widget=None 插件,默认select插件 label=None Label内容 initial=None 初始值 help_text='' 帮助提示 TypedChoiceField(ChoiceField) coerce = lambda val: val 对选中的值进行一次转换,通过lambda函数实现 empty_value= '' 空值的默认值 MultipleChoiceField(ChoiceField) 多选框 TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 对选中的每一个值进行一次转换 empty_value= '' 空值的默认值 ComboField(Field) fields=() 使用多个验证,<br />如下:即验证最大长度20,又验证邮箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用,提供接口,需要自己实现 SplitDateTimeField(MultiValueField) input_date_formats=None 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中 path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True 允许文件 allow_folders=False, 允许文件夹 required=True widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符) UUIDField(CharField) uuid类型
注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串NullBooleanField(BooleanField) BooleanField(Field) URLField(Field) EmailField(CharField) **FloatField(IntegerField)** 2-2 form内widget属性
TextInput(Input) input type="text" NumberInput(TextInput) 数字输入框 EmailInput(TextInput) 邮箱输入框 URLInput(TextInput) url输入框 PasswordInput(TextInput) 密码输入框 HiddenInput(TextInput) 隐藏输入框 Textarea(Widget) textarea文本区 DateInput(DateTimeBaseInput) 日期输入框 DateTimeInput(DateTimeBaseInput) 日期时间输入框 TimeInput(DateTimeBaseInput) 时间输入框 CheckboxInput 多选框 Select 下拉框 NullBooleanSelect 非空布尔值下拉框 SelectMultiple 多选下拉框 RadioSelect 单选框 CheckboxSelectMultiple 多选checkbox ??? FileInput 文件上传 ClearableFileInput MultipleHiddenInput 多隐藏输入框 SplitDateTimeWidget 时间分割框(两个input框) SplitHiddenDateTimeWidget SelectDateWidget 2-3 常用选择属性 - radio、select、checkbox
# 单 radio,值为字符串 user = fields.CharField( initial=2, widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) ) # 单 radio,值为字符串 user = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.RadioSelect ) # 单 select,值为字符串 user = fields.CharField( initial=2, widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) ) # 单 select,值为字符串 user = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.Select ) # 多选 select,值为列表 user = fields.MultipleChoiceField( choices=((1,'上海'),(2,'北京'),), initial=[1,], widget=widgets.SelectMultiple ) # 单 checkbox user = fields.CharField( widget=widgets.CheckboxInput() ) # 多选 checkbox,值为列表 user = fields.MultipleChoiceField( initial=[2, ], choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxSelectMultiple
class MyForm(forms.Form): name = forms.CharField(max_length=8, min_length=3, label='用户名', widget=forms.widgets.TextInput( attrs={'class': 'form-control'} # 使用 attrs 修改id、class等内容 )) pwd = forms.CharField(max_length=8, min_length=3, required=True, label='密码', widget=forms.widgets.PasswordInput()) re_pwd = forms.CharField(max_length=8, min_length=3, required=True, label='确认密码', widget=forms.widgets.PasswordInput()) email = forms.EmailField(label='邮箱', widget=forms.widgets.EmailInput()) url = forms.URLField(widget=forms.widgets.URLInput()) file = forms.FileField(widget=forms.widgets.FileInput()) chock_box = forms.CharField(widget=forms.widgets.CheckboxInput()) select_box = forms.CharField(widget=forms.widgets.CheckboxSelectMultiple( choices=((1,'上海'),(1,'北京'))))
三、模板错误信息渲染(form形式提交数据)
注意:
- novalidate - 取消浏览器自带的校验信息,为了测试错误信息在form提交之后显示
- 前端使用 foo.errors.0 获取抛出的错误信息
- 类内定义字段时使用 error_messages 重写默认校验错误信息
- 全局钩子函数中的错误会放入__all__对象内
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms from django.core.exceptions import ValidationError class MyForm(forms.Form): name = forms.CharField(max_length=8, min_length=3, label='用户名', widget=forms.widgets.TextInput(), error_messages={'max_length': '超出长度范围,8', 'min_length': '小于长度范围,3', 'required': '必填选项', }) pwd = forms.CharField(max_length=8, min_length=3, required=True, label='密码', widget=forms.widgets.PasswordInput(), error_messages={'max_length': '超出长度范围,8', 'min_length': '小于长度范围,3', 'required': '必填选项', } ) re_pwd = forms.CharField(max_length=8, min_length=3, required=True, label='确认密码', widget=forms.widgets.PasswordInput(), error_messages={'max_length': '超出长度范围,8', 'min_length': '小于长度范围,3', 'required': '必填选项', } ) email = forms.EmailField(label='邮箱', error_messages={'required': '必填选项', 'invalid': '非法格式'} ) # 用户名校验 def clean_name(self): name = self.cleaned_data.get('name') if name.startswith('sb'): raise ValidationError('不能以sb开头') return name def clean(self): pwd = self.cleaned_data.get('pwd') re_pwd = self.cleaned_data.get('re_pwd') if pwd == re_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致') def view_form(request): if request.method == 'GET': myform = MyForm() elif request.method == 'POST': myform = MyForm(request.POST) if myform.is_valid(): return HttpResponse('登陆成功') else: # 全局钩子的ValidationError 自定义错误被保存在nyform对象errors的__all__私有属性下 print(myform.errors) # ErrorDict : {"校验错误的字段":["错误信息",]} # <ul class="errorlist"><li>email<ul class="errorlist"><li>非法格式</li></ul></li><li>__all__<ul class="errorlist nonfield"><li>两次密码不一致</li></ul></li></ul> all_error = myform.errors.get('__all__') print(all_error) # <ul class="errorlist nonfield"><li>两次密码不一致</li></ul> if all_error: all_error = all_error[0] print(all_error) # 两次密码不一致 print(myform.errors.as_data) # <bound method ErrorDict.as_data of {'email': ['非法格式'], '__all__': ['两次密码不一致']}> print(type(myform.errors.as_data)) print(myform.errors.as_data()) # {'email': [ValidationError(['非法格式'])], '__all__': [ValidationError(['两次密码不一致'])]} return render(request, 'forms.html', locals())
<form action="" method="post" novalidate> {% for foo in myform %} <p>{{ foo.label }}:{{ foo }}<span> {{ foo.errors.0 }}</span> </p> {% endfor %} <input id = 'btn' type="submit" value="提交"> </form>