django表单使用
一、表单常用字段类型及参数
表单可以自动生成html代码,每一个字段默认有一个html显示样式,大多数默认为输入框。
字段相当于正则表达式的集合,能够对表单传入的数据进行校验,并且某一部分校验失败时会保留另一部分校验成功的值。
使用表单时首先需要导入forms模块和forms的fields模块,再定义一个继承forms.Form的类,实例化后在模板中通过调用实例化对象的属性生成输入框。
field:这个一般不直接使用,用于被其他字段继承
required=True, 是否允许为空
label=None, 用于生成显示内容,如果不定义label,则显示的内容为首字母大写的字段名
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 例如 {'required': '不能为空', 'invalid': '格式错误'},是一个字典,key表示每一个表达式的code,value表示如果在对应的code上发生错误,后台可以捕捉到的错误信息并返给前台与用户交互,其中value又是一个列表
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀
widget=None, 生成HTML插件
1.BooleanField(Field):布尔值,相当于单选框
2.CharField(Field):字符串
max_length最大长度,min_length最小长度,strip是否移除用户输入的空格
3.EmailField(CharField):邮箱
invalid格式是否合法
4.IntegerField(Field):整数
invalid格式是否合法、max_value最大值、min_value最小值
5.FloatField(IntegerField):浮点类型
6.DecimalField(IntegerField):浮点类型
max_digits(总长度)、decimal_places(小数位长度)
7.FileField(Field):上传文件、ImageField(Field)上传图片
allow_empty_file是否允许空文件,上传文件需要在form表单指定enctype="multipart/form-data",并且要通过request.FILES接收
upload_to:指定上传路径
8.ChoiceField(Field):单选下拉列表
9.MultipleChoiceField(ChoiceField):多选下拉列表
10.TypedChoiceField(ChoiceField))
可对传入的数据进行一次类型转化coerce = lambda x: int(x)
11.GenericIPAddressField(CharField):ip地址
protocol='both'表示同时支持ipv4和ipv6的地址
12.DateField(BaseTemporalField),日期,2019-05-10,
13.TimeField(BaseTemporalField),时间,14:23
14.DateTimeField(BaseTemporalField),日期和时间,2019-05-10 14:23
15.URLField:接收URL格式的字符串
二、django内置插件
使用django的内置html插件时,需要先导入forms模块的widgets模块,from django.forms import widgets。
对于CharField字段,默认显示的是文本框,如果希望显示成单选、多选或下拉列表的形式,则需要用到widgets定制插件。
TextInput(Input)
EmailInput(TextInput)
NumberInput(TextInput)
RadioSelect(ChoiceWidget)
Select(ChoiceWidget)
SelectMultiple(Select)
CheckboxInput(Input)
CheckboxSelectMultiple(ChoiceWidget)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
URLInput(TextInput)
PasswordInput(TextInput)
FileInput
HiddenInput(TextInput)
NullBooleanSelect
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
1.定制单选radio、单选下拉列表、多选下拉列表、单选框和多选框:通过CharField、ChoiceField和MutipleChoiceField字段
对于单选radio,第一种写法使用CharField字段,该字段默认显示为输入框,通过widget=widgets.RadioSelect插件定制为单选框样式,并将choices作为参数传递给该插件。
第二种写法使用ChoiceField字段,该字段默认显示为下拉列表,通过widget=widgets.RadioSelect插件定制为单选框样式,并将choices作为参数传递给该字段。
通过widgets定制插件时,可同时给字段加上自定义属性,例如如下hobby8和hobby9。
#单选radio
hobby1 = fields.CharField(label='爱好1',widget=widgets.RadioSelect(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=1)
hobby2 = fields.ChoiceField(label='爱好2',widget=widgets.RadioSelect,choices=((1,'篮球'),(2,'足球'),(3,'乒乓球')),initial=1)
#单选下拉列表
hobby3 = fields.CharField(label='爱好3',widget=widgets.Select(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=3)
hobby4 = fields.ChoiceField(label='爱好4', widget=widgets.Select,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=3)
#多选下拉列表
hobby5 = fields.CharField(label='爱好5', widget=widgets.SelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球'))), initial=[1, 2])
hobby6 = fields.MultipleChoiceField(label='爱好6', widget=widgets.SelectMultiple,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=[1,2])
#单选框
hobby7 = fields.CharField(label='是否同意',widget=widgets.CheckboxInput())
#多选框
hobby8 = fields.CharField(label='爱好8', widget=widgets.CheckboxSelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),attrs={'name':'hobby8'}), initial=[1, 2])
hobby9 = fields.MultipleChoiceField(label='爱好9',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby9'}),choices=((1, '篮球'), (2, '足球'), (3,'乒乓球'),initial=[1, 2])
定制radio、select和checkbox

2.扩展正则
如果某一字段自带的验证方法不足以进行验证,可以自定义验证方法,这需要通过RegexField字段或者validators=[]参数完成
#单选radio
hobby1 = fields.CharField(label='爱好1',widget=widgets.RadioSelect(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=1)
hobby2 = fields.ChoiceField(label='爱好2',widget=widgets.RadioSelect,choices=((1,'篮球'),(2,'足球'),(3,'乒乓球')),initial=1)
#单选下拉列表
hobby3 = fields.CharField(label='爱好3',widget=widgets.Select(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=3)
hobby4 = fields.ChoiceField(label='爱好4', widget=widgets.Select,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=3)
#多选下拉列表
hobby5 = fields.CharField(label='爱好5', widget=widgets.SelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球'))), initial=[1, 2])
hobby6 = fields.MultipleChoiceField(label='爱好6', widget=widgets.SelectMultiple,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=[1,2])
#单选框
hobby7 = fields.CharField(label='是否同意',widget=widgets.CheckboxInput())
#多选框
hobby8 = fields.CharField(label='爱好8', widget=widgets.CheckboxSelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),
attrs={'name':'hobby7'}), initial=[1, 2])
hobby9 = fields.MultipleChoiceField(label='爱好9',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby8'}),
choices=((1, '篮球'), (2, '足球'), (3,'乒乓球'),initial=[1, 2])
定制radio、select和checkbox
通过validators=[]属性定制时,可以自定义多个规则RegexValidator,每一个规则的第一个参数为规则,第二个规则为对应的错误信息
通过RegexField字段定制时,只能定制一个规则。
三、表单使用实例
1.forms的py文件
class UserForm(forms.Form):
username = fields.CharField(label='姓名',required=True,max_length=15,error_messages={'max_length':'too long'})
age = fields.IntegerField(label='年龄',required=True,min_value=18,error_messages={'invalid':'请输入整数','min_value':'不符合劳动法'})
birth = fields.DateField(label='入职时间',required=True)
email = fields.EmailField(label='邮箱',required=True,error_messages={'invalid':'请输入有效格式的邮箱'})
gender = fields.CharField(label='性别', widget=widgets.RadioSelect(choices=((1, '男'), (2, '女'))), initial=1)
resume = fields.FileField(label='简历')
city = fields.CharField(label='省份',widget=widgets.Select())
hobby = fields.MultipleChoiceField(label='爱好',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby8'}),
choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),initial=[1,2])
proto = fields.CharField(label='是否已阅协议', widget=widgets.CheckboxInput())
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['city'].widget.choices = Province.objects.all().values_list()
#假设定义了一个省份的类存放在数据库,为了数据库的内容变化能在页面刷新时显示到页面上,需要进行init操作并将数据库的值赋值给city字段
定义UserForm
2.处理函数的py文件
def add_user(request):
if request.method == 'GET':
obj = UserForm() #实例化一个空的表单
return render(request,'add_user.html',{'obj':obj})
elif request.method =='POST':
obj = UserForm(request.POST,request.FILES) #传入的文件需要通过request.FILES接收,其他通过request.POST接收,一起传递给表单类进行实例化
if obj.is_valid(): #判断输入是否有效
print(type(obj.fields))
print(obj.fields)
print(type(obj.cleaned_data))
print(obj.cleaned_data) #打印输入内容
print(obj.cleaned_data['username']) #获取输入的username值
print(obj.cleaned_data.get('email')) #获取输入的email值
UserInfo.object.create(**obj.cleaned.data) # UserForm表单对应了数据库中的表UserInfo
else:
print(type(obj.errors))
print(obj.errors.get_json_data())#打印错误信息,如果需要打印错误信息,还需要在form中指定novalidate属性
return render(request,'add_user.html',{'obj':obj})
else:
return redirect('http://www.baidu.com')
处理函数
①obj.is_valid()方法
obj.is_valid()表示判断输入是否满足Form各字段的要求,实例化一个非空的表单,在实例化的时候并没有生成html标签,也没有进行表单验证,生成html标签并且进行表单验证是在is_valid()时进行的。obj.cleaned_data表示键值和对应的输入值。
如果在实例化表单的时候通过inital传值,即obj = UserForm(inital = (request.POST,request.FILES) ),在实例化的时候不会进行表单验证。
②obj.fields属性
obj.fields表示表单的所有字段,类型为<class 'collections.OrderedDict'>。
③obj.cleaned_data属性
在is_valid之前没有cleaned_data,cleaned_data是在进行验证之后才生成,类型为<class 'dict'>
④obj.errors
obj.errors表示错误信息,类型为<class 'django.forms.utils.ErrorDict'>
错误信息默认是以as_ul()进行显示的,其他显示方式还有as_data()、as_json()、as_text()、get_json_Data(),常用get_json_Data()。
3.模板文件
在渲染form对象时,可以以as_table表格、as_ul无序列表、as_p段落等方式进行渲染。
<form action="add_user" method="post" enctype="multipart/form-data"> <!--如果需要上传文件,则form中应指定enctype属性为multipart/form-data-->
{% csrf_token %}
<table>
{{ obj.as_table }} <!--将表单以表格形式渲染-->
</table>
<input type="submit">
</form>
模板文件
页面显示内容为,并且如果按照要求输入数据,pycharm打印的信息如下。


如果在form中指定invalidate属性,假设不输入年龄、不按格式输入邮箱,那么打印的错误信息如下

另外一种模板渲染方式
<form action="add_user" method="post" enctype="multipart/form-data" novalidate>
<!--如果需要上传文件,则form中应指定enctype属性为multipart/form-data-->
{% csrf_token %}
<p>{{ obj.username.label }}{{ obj.username }}{{ obj.errors.0 }}</p>
<p>{{ obj.age.label }}{{ obj.age }}{{ obj.errors.0 }}</p>
<p>{{ obj.birth.label }}{{ obj.birth }}{{ obj.errors.0 }}</p>
<p>{{ obj.email.label }}{{ obj.email }}{{ obj.errors.0 }}</p>
<p>{{ obj.gender.label }}{{ obj.gender }}{{ obj.errors.0 }}</p>
<p>{{ obj.resume.label }}{{ obj.resume }}{{ obj.errors.0 }}</p>
<p>{{ obj.city.label }}{{ obj.city }}{{ obj.errors.0 }}</p>
<p>{{ obj.hobby.label }}{{ obj.hobby }}{{ obj.errors.0 }}</p>
<p>{{ obj.proto.label }}{{ obj.proto }}{{ obj.errors.0 }}</p>
<input type="submit">
</form>
另一种模板渲染方式
四、表单与数据库是否重复验证
上述方法已经可以可以对各字段进行格式、大小、长度等验证,但是表单提交的数据通常要写入数据库,为了防止写入违反唯一性约束的两条相同记录,还需要验证增加的数据是否已经在数据库中存在。
1.对于单一字段
可在表单类时同时定义表单的方法,方法名称为clean_验证字段名,假如上述例子UserForm表单对应了的数据库中的表UserInfo,假如UserInfo表中的username不可重复,那么在定义表单时可通过增加clean_username()方法实现。
#from django.core.exceptions import ValidationError导入异常类
class UserForm(forms.Form):
username = fields.CharField(label='姓名',required=True,max_length=15,error_messages={'max_length':'too long'})
……
def clean_username(self): #定义clean_字段名的方法
v= self.cleaned_data['username'] #
if UserInfo.objects.filter(username=v).count(): #
raise ValidationError('用户名已经存在','repeat') #抛出异常,第一个参数为error_message,第二个为code
return v
表单对单一字段验证
2.对于多个字段
在定义表单类的同时定义clean()方法,假如username和age字段不可同时重复
#from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
class UserForm(forms.Form):
……
def clean(self):
value_dic = self.cleaned_data
v1 = value_dic.get('username')
v2 = value_dic.get('email')
if UserInfo.objects.filter(username=v1,email=v2).count():
raise ValidationError('total error')
return value_dic
表单对多个字段验证
因为这一类错误不属于单一的字段,因此在errors中显示的错误字段为__all__(也即NON_FIELD_ERRORS),而在模板页面只能通过v.non_field_errors(小写)获取整体错误信息,不能通过v.__all__获取。
表单字段类型可参考http://www.cnblogs.com/wupeiqi/articles/6144178.html
django表单使用的更多相关文章
- python 全栈开发,Day111(客户管理之 编辑权限(二),Django表单集合Formset,ORM之limit_choices_to,构造家族结构)
昨日内容回顾 1. 权限系统的流程? 2. 权限的表有几个? 3. 技术点 中间件 session orm - 去重 - 去空 inclusion_tag filter 有序字典 settings配置 ...
- python3之Django表单(一)
1.HTML中的表单 在HTML种,表单是在<form>...</form>种的元素,它允许用户输入文本,选择选项,操作对象等,然后发送这些数据到服务器 表单元素允许用户在表单 ...
- django表单的api
django表单的api,参考文档:https://yiyibooks.cn/xx/Django_1.11.6/ref/forms/api.html 绑定与未绑定形式: Form要么是绑定的,要么是未 ...
- Django表单API详解
声明:以下的Form.表单等术语都指的的广义的Django表单. Form要么是绑定了数据的,要么是未绑定数据的. 如果是绑定的,那么它能够验证数据,并渲染表单及其数据,然后生成HTML表单.如果未绑 ...
- 9:django 表单
django自带表单系统,这个表单系统不仅可以定义属性名,还可以自己定义验证,更有自己自带的错误提示系统 这节我们仅仅粗略的来看一下django表单系统的入门运用(具体的实在太多东西,主要是我觉得有很 ...
- django 表单系统 之 forms.Form
继承forms.Form实现django表单系统 参考: https://www.cnblogs.com/zongfa/p/7709639.html https://www.cnblogs.com/c ...
- 关于创建Django表单Forms继承BaseForm的问题
在创建Django表单时,因为需要验证用户输入的验证码是否正确,因此需要在session里提取当前验证码的值和POST提交过来的值进行比对,如图: form.py from django import ...
- Django 表单处理流程
Django 的表单处理:视图获取请求,执行所需的任何操作,包括从模型中读取数据,然后生成并返回HTML页面(从模板中),我们传递一个包含要显示的数据的上下文.使事情变得更复杂的是,服务器还需要能够处 ...
- 第四章:Django表单 - 2:Django表单API详解
声明:以下的Form.表单等术语都指的的广义的Django表单. Form要么是绑定了数据的,要么是未绑定数据的. 如果是绑定的,那么它能够验证数据,并渲染表单及其数据,然后生成HTML表单.如果未绑 ...
- 第四章:Django表单 - 1:使用表单
假设你想从表单接收用户名数据,一般情况下,你需要在HTML中手动编写一个如下的表单元素: <form action="/your-name/" method="po ...
随机推荐
- ajax前后端交互原理(5)
5.ajax简介 5.1.什么是ajax Asynchronous JavaScript and XML ,异步的javascript和XML 5.2.使用ajax有什么用 数据交互,可以从服务器获取 ...
- java.math.BigDecimal cannot be cast to [Ljava.lang.Object;
从数据库中使用sum函数取出统计值后,放进list中,遍历list的时候强转化成Object是报错. BigDecimal .Integer不是基本类型,是int的包装类,无法把包装当做基本类型来用. ...
- FTP学习
FTP服务的使用 一.LVM理论 介绍 FTP用于在Internet 上控制文件的双向传输. FTP的主要作用就是让用户连接一 个远程计算机(这些计算机上 运行着FTP服务器程序) ,并查看远程计算机 ...
- web开发相关概念
什么是web通信? WEB采用B/S通信模式,通过超文本传送协议(HTTP, Hypertext transport protocol)进行通信.通过浏览器地址栏编写URL,向服务器发送一个请求,服务 ...
- (私人收藏)清新文艺唯美PPT模板
清新文艺唯美PPT模板 https://pan.baidu.com/s/12hP5pT2KfPGCgOnvp0rOIAf0dj
- 每日一题 - 剑指 Offer 50. 第一个只出现一次的字符
题目信息 时间: 2019-07-03 题目链接:Leetcode tag:哈希表 难易程度:简单 题目描述: 在字符串 s 中找出第一个只出现一次的字符.如果没有,返回一个单空格. s 只包含小写字 ...
- Xenon's Attack on the Gangs(树规)
题干 Input Output Example Test 1: Test 2: 3 5 1 2 1 2 2 3 1 3 1 4 3 5 3 10 Tips 译成人话 给n个结点,n-1条无向边.即一棵 ...
- POJ3262贪心
题意:FJ去砍树,然后和平时一样留了 N (2 ≤ N ≤ 100,000)头牛吃草.当他回来的时候,他发现奶牛们正在津津有味地吃着FJ种的美丽的花!为了减少后续伤害,FJ决定立即采取行动:运输每头牛 ...
- SCSS笔记
SASS是成熟,稳定,强大的 CSS预处理器 ,而 SCSS 是SASS3版本当中引入的新语法特性,完全兼容CSS3的同时继承了CSS强大的动态功能. CSS书写代码规模较大的web应用时,容易造成选 ...
- __stdcall、__cdcel和__fastcall三者的区别
转自:https://www.cnblogs.com/huhewei/p/6080143.html 一.概述 __stdcall.__cdecl和__fastcall是三种函数调用协议,函数调用协议会 ...