Flask 扩展 表单
pip install flask-wtf
一个简单的表单
from flask_wtf import Form
from wtforms import StringField
from wtforms.validators import DataRequired class MyForm(Form):
user = StringField('Username', validators=[DataRequired()])
表单类MyForm定义个了一个字符型字段,也就是一个文字输入框”user”。StringField的第一个参数”Username”指定了该字段的显示名,第二个参数指定了验证规则。这是一个列表,也就是你可以对一个字段定义多个验证规则,上例中我们使用了”wtforms.validators.DataRequired”验证,也就是代表了该字段为必填项,表单提交时必须非空。
下一步,我们写个视图函数login来使用MyForm表单
from flask import Flask, render_template
app = Flask(__name__)
app.secret_key = '' @app.route('/login', methods=('GET', 'POST'))
def login():
form = MyForm()
if form.validate_on_submit():
# if form.user.data == 'admin':
if form.data['user'] == 'admin':
return 'Admin login successfully!'
else:
return 'Wrong user!'
return render_template('login.html', form=form)
有了这个”form.validate_on_submit()”方法,我们就不用像之前一样通过请求方法是否为”POST”来判断表单是否提交。在表单提交后,我们可以用表单对象的data属性来获取提交内容,这个”form.data”是一个字典类型。上例中,它只有一个字段,也就是”user”。我们同样也可以用”form.user.data”获取”user”字段的值。在非提交状态下,我们就渲染模板,并且往模板中传入表单对象。另外注意,这里要设置”app.secret_key”,因为表单类中会使用到会话对象session。
最后让我们写”login.html”模板来显示这个表单:
<form method="POST" action="{{ url_for('login') }}">
{{ form.hidden_tag() }}
{{ form.user.label }}: {{ form.user(size=20) }}
<input type="submit" value="Submit">
</form>
表单中,”form.hidden_tag()”会生成一个隐藏的”<div>”标签,其中会渲染任何隐藏的字段,最主要的是CSRF字段。这个CSRF(Cross-Site Request Forgery跨站请求伪造)是一种通过伪装来自受信任用户的请求,来发送恶意攻击的方法,具体内容大家可以在网上搜到。WTForms默认开启CSRF保护,如果你想关闭它(建议不要这样做),可以在实例化表单时传入参数,比如”form = MyForm(csrf_enabled=False)”。
“form.user.label”会输出”user”字段的显示名,即上例中的”Username”;”form.user”会输出一个”text”类型的”<input>”标签,它的参数”size=20″会成为这个”<input>”标签里的属性。所以上面的模板内容在渲染后,会被转换为下面这段HTML代码:
<form method="POST" action="/login">
<div style="display:none;"><input id="csrf_token" name="csrf_token" type="hidden" value="1458707165##33a1f1384d3c12dca29cce5e8ccf6e4d21f5f28f"></div>
<label for="user">Username</label>: <input id="user" name="user" size="" type="text" value="">
<input type="submit" value="Submit">
</form>
运行返回如下结果
当我们输入”admin”时,返回成功;输入其他字符串时,返回失败;而不输入直接提交,会返回表单页
表单字段类型
WTForms提供了大量内置的字段类型,来便于我们创建表单项,它们都放在”wtforms.fields”包下。下面,我们创建一个用户注册表单类,并将常用的字段类型都包括在其中,为了方便理解,描述就直接写在注释里:
from wtforms.fields import (StringField, PasswordField, DateField, BooleanField,
SelectField, SelectMultipleField, TextAreaField,
RadioField, IntegerField, DecimalField, SubmitField)
from wtforms.validators import DataRequired, Length, Email, EqualTo, NumberRange class RegisterForm(Form):
# Text Field类型,文本输入框,必填,用户名长度为4到25之间
username = StringField('Username', validators=[Length(min=4, max=25)]) # Text Field类型,文本输入框,Email格式
email = StringField('Email Address', validators=[Email()]) # Text Field类型,密码输入框,必填,必须同confirm字段一致
password = PasswordField('Password', [
DataRequired(),
EqualTo('confirm', message='Passwords must match')
]) # Text Field类型,密码输入框
confirm = PasswordField('Repeat Password') # Text Field类型,文本输入框,必须输入整型数值,范围在16到70之间
age = IntegerField('Age', validators=[NumberRange(min=16, max=70)]) # Text Field类型,文本输入框,必须输入数值,显示时保留一位小数
height = DecimalField('Height (Centimeter)', places=1) # Text Field类型,文本输入框,必须输入是"年-月-日"格式的日期
birthday = DateField('Birthday', format='%Y-%m-%d') # Radio Box类型,单选框,choices里的内容会在ul标签里,里面每个项是(值,显示名)对
gender = RadioField('Gender', choices=[('m', 'Male'), ('f', 'Female')],
validators=[DataRequired()]) # Select类型,下拉单选框,choices里的内容会在Option里,里面每个项是(值,显示名)对
job = SelectField('Job', choices=[
('teacher', 'Teacher'),
('doctor', 'Doctor'),
('engineer', 'Engineer'),
('lawyer', 'Lawyer')
]) # Select类型,多选框,choices里的内容会在Option里,里面每个项是(值,显示名)对
hobby = SelectMultipleField('Hobby', choices=[
('swim', 'Swimming'),
('skate', 'Skating'),
('hike', 'Hiking')
]) # Text Area类型,段落输入框
description = TextAreaField('Introduction of yourself') # Checkbox类型,加上default='checked'即默认是选上的
accept_terms = BooleanField('I accept the Terms of Use', default='checked',
validators=[DataRequired()]) # Submit按钮
submit = SubmitField('Register')
每个字段类型的第一个参数都是显示名,而且都接收”validator”参数来传入验证规则。上例的表单字段上,我们用到了很多验证规则,关于这部分,我们会在下一小节介绍。对于时间日期字段,如”DateField”或”DateTimeField”,它们都有一个”format”参数来传入可识别的日期格式;对于选择框,如”RadioField”, “SelectField”或”SelectMultipleField”,它们都有一个”choices”参数来传入可选择项,每个项是一个”(值, 显示名称)”对,同时它们也有一个参数”coerce”参数来强制转换选择项值的类型,比如”coerce=int”。
接下来,让我们编写模板,因为字段比较多,我们先写一个宏来渲染单个字段,并存放在模板文件”_field.html”中:
{% macro render_field(field) %}
<tr>
<td>{{ field.label }}</td>
<td>{{ field(**kwargs)|safe }}</td>
<td>{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</td>
</tr>
{% endmacro %}
这个”render_field”宏用来渲染表格中的一个行,它有三个列,分别是字段显示名,字段值,和错误信息(如果有错误的话)。然后,我们写”register.html”模板:
<!doctype html>
<title>Registration Form Sample</title>
<h1>User Registration</h1>
{% from "_field.html" import render_field %}
<form method="POST" action="{{ url_for('register') }}">
{{ form.hidden_tag() }}
<table>
{{ render_field(form.username) }}
{{ render_field(form.email) }}
{{ render_field(form.password) }}
{{ render_field(form.confirm) }}
{{ render_field(form.age) }}
{{ render_field(form.height) }}
{{ render_field(form.gender) }}
{{ render_field(form.birthday) }}
{{ render_field(form.job) }}
{{ render_field(form.hobby) }}
{{ render_field(form.description) }}
{{ render_field(form.accept_terms) }}
</table>
{{ form.submit }}
</form>
模板中导入”render_field”宏,并依次渲染用户注册表单里的每一个字段。最后,我们写个视图函数来显示这个表单:
@app.route('/register', methods=('GET', 'POST'))
def register():
form = RegisterForm()
if form.validate_on_submit():
flash('User "%s" registered successfully! Please login.' % form.username.data)
login_form = LoginForm()
return render_template('login.html', form=login_form) return render_template('register.html', form=form)
打开浏览器,访问”/register”地址,你会看到这样的表单页面:
如果你什么都不输入,直接提交,错误信息将会在字段旁显示:
这个页面还很丑陋,你可以通过CSS来美化它,本文就不介绍了。总之,大家已经被WTForms的强大感染到了吧!
验证规则
上一节的例子中其实已经把大部分常用的验证规则validator都用上了,WTForms同样提供了大量内置的验证规则,它们都放在”wtforms.validators”包下。这里我们就来列举一下:
验证规则 | 说明 |
---|---|
DataRequired | 验证必填项 |
验证邮件地址格式 | |
EqualTo | 验证必须同另一个字段值相同,它需传入另一个字段的名称”fieldname” |
Length | 验证输入字符串长度,它有两个参数:”min”最小长度,”max”最大长度,缺省的话就不检查 |
NumberRange | 验证输入数值的范围,它有两个参数:”min”最小值,”max”最大值,缺省的话就不检查 |
URL | 验证URL格式 |
IPAddress | 验证IP地址格式,默认IPV4,你可以传入”ipv6=True”来验证IPV6地址 |
MacAddress | 验证Mac地址格式 |
AnyOf | 传入一个列表作为参数,验证是否匹配列表中的任一值 |
NoneOf | 传入一个列表作为参数,验证是否与列表中的所有值都不同 |
Regexp | 正则表达式验证,需传入一个正则表达式,它还有一个flags参数,如果你传入”re.IGNORECASE”,就会忽略大小写 |
所有的validator都有一个”message”参数,用来指定当验证失败时抛出的错误消息,不指定的话WTForms就会使用默认错误消息。
文件上传
WTForms本身有一个”FileField”用来处理文件上传功能,Flask-WTF扩展对其作了封装,使得我们可以更方便的在Flask应用中实现文件上传。现在就让我们来定义一个文件上传的表单类:
from flask_wtf.file import FileField, FileAllowed, FileRequired class AttachForm(Form):
attach = FileField('Your Attachment', validators=[
FileRequired(),
FileAllowed(['jpg', 'png'], 'Images only!')
])
我们引入”flask_wtf.file”包下的文件上传框”FileField”,和两个验证规则”FileRequired”及”FileAllowed”。”FileRequired”验证表单提交时必须有文件已被指定;”FileAllowed”验证文件的类型,上例中只接收以”jpg”和”png”为后缀的文件,如果不是会抛出错误消息”Images only!”。
模板文件很简单,只要记得在”<form>”标签里加上属性’enctype=”multipart/form-data”‘即可:
<form method="POST" action="{{ url_for('upload') }}" enctype="multipart/form-data">
{{ form.hidden_tag() }}
{{ form.attach.label }} {{ form.attach }}
<input type="submit" value="Submit">
</form>
最后,写上视图函数:
from werkzeug import secure_filename @app.route('/upload', methods=('GET', 'POST'))
def upload():
form = AttachForm()
if form.validate_on_submit():
filename = secure_filename(form.attach.data.filename)
form.attach.data.save('uploads/' + filename)
return 'Upload successfully!'
“secure_filename”用来确保文件名安全,我们在介绍Flask文件和流时有提到过。”form.attach.data”就可以获取文件的内容,它的”save()”方法可以将内容保存到本地文件中去。上例中,我们把文件保存在本地当前目录下的”uploads”子目录中。运行下这段程序,你将看到下图这样的表单,你可以试着上传一个文件。
表单字段国际化
由于表单类是在Flask上下文环境外定义的,对于其字段显示名的国际化,要使用”lazy_gettext”方法。比如:
from flask_wtf import Form
from flask_babel import lazy_gettext
from wtforms import StringField
from wtforms.validators import DataRequired class MyForm(Form):
user = StringField(lazy_gettext(u'Username'), validators=[DataRequired()])
从Flask-WTF版本0.13开始,”flask_wtf.Form”类被标为”过时”了,取而代之的是”flask_wtf.FlaskForm”类。大家只需要将上面使用到Form的例子都改为FlaskForm就行了。
Flask 扩展 表单的更多相关文章
- flask之表单验证 2018.12.23
#flask的消息闪现依赖于flash库,用户发送的请求方式存储在request模块中 #跳转依赖于redirect模块,还可以通过url_for方法来进行方法上的寻址 from flask impo ...
- Flask入门 表单Flask-wtf form原生 Bootstrap渲染(七)
(1) 原生的表单 模板页面,form表单form.html <form action="{{ url_for('/check/') }}" method='post'> ...
- Flask:web表单
客户端发送的所有通过POST发出的请求信息都可以通过request.form获取.但是如果我们要生成表单的HTML代码和验证提交的表单数据那么就需要采用另外的方法.Flask-WTF扩展可以把处理we ...
- flask web 表单验证 WTForms
简介 WTForms 是一个flask集成框架,或者说是库,用于处理浏览器表单提交的数据,它在flask-WTF的基础上扩展并添加了一些随手可得的精巧帮助函数,这些函数将会是在flask里使用表单更加 ...
- flask 后台表单验证模块
我不想直接用flask的wtf模块,太大,功能太多,用不了.但后台也不能不做验证吧,我比较懒,不想一行一行写代码验证,所以就写了一个验证模块,对于小项目也够用了 # encoding=utf-8 # ...
- flask form表单验证
新建forms.py文件 #!/usr/bin/env python #-*-coding:utf--*- #导入模块 from flask_wtf import FlaskForm #FlaskFo ...
- flask 单个表单多个提交按钮
单个表单多个提交按钮 在某些情况下,可能需要为一个表单添加多个提交按钮.比如在创建文章的表单中添加发布按钮和存草稿的按钮.当用户提交表单时,需要在视图函数中根据按下的按钮来做出不同的处理. 下面例子中 ...
- flask 处理表单数据
处理表单数据 表单数据的处理涉及很多内容,从获取数据到保存数据大致有以下步骤: 1. 解析请求,获取表单数据 2. 对数据进行必要的转换,比如讲勾选框的值转换成python的布尔值 3. 验证数 ...
- flask之表单
一:表单 表单用于注册,修改用户数据等场景. flask-wtf提供了一个包,可以创建表单:pip install flask-wtf 为了防止跨域请求,flask_wtf自己生成一个秘钥,用秘钥生成 ...
随机推荐
- mfc100u.dll下载和使用方法
当运行软件或游戏时,系统提示"丢失mfc100u.dll"."没有找到mfc100u.dll"等类似错误信息. 请下载本站提供的dll文件,使用它可以帮助用 ...
- Struts2如何实现MVC,与Spring MVC有什么不同?
Struts2采用filter充当前端控制器处理请求,filter会根据Struts.xml的配置,将请求分发给不同的业务控制器Action,再由Action处理具体的业务逻辑.Action处理完业务 ...
- mybatis快速入门(七)-spring-mybatis整合
今天写写spring-mybatis整合吧,先写个原始dao类的整合,下一节在写个动态代理的整合,我就不写太详细了,因为前面的章节基本上都有了,我直接就一口气都写出来需要那些文件然后在直接贴代码,首先 ...
- 【LightOJ1259】Goldbach`s Conjecture(数论)
[LightOJ1259]Goldbach`s Conjecture(数论) 题面 Vjudge T组询问,每组询问是一个偶数n 验证哥德巴赫猜想 回答n=a+b 且a,b(a<=b)是质数的方 ...
- 【BZOJ2002】弹飞绵羊(Link-Cut Tree)
[BZOJ2002]弹飞绵羊(Link-Cut Tree) 题面 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lost ...
- 进一步理解阿贾克斯(Ajax)
一.ajax简介 1.Asynchronous JavaScript and XML(异步的Javascript和XML) 2.是一种在无需重新加载整个网页的情况下能够更新部分网页的技术. 二.aja ...
- 基于socket实现的简单的聊天程序
记得八年前第一次使用socket做的一个五子棋程序,需要序列化棋子对象,传递到对方的电脑上. 一个偶然的机会,第二次使用socket做点事情.先看聊天服务器端的实现: 服务器端要实现以下功能: ...
- js文本框字符数输入限制
我们常常在前台页面做一些文本输入长度的验证,为什么呢?因为数据库字段设置了大小,如果不限制输入长度,那么写入库时就会引发字符串截断异常.今天就给大家分享一个jquery插件来解决这一问题. (func ...
- MinGW安装和使用
P.S.安装MinGW主要是code blocks 编译出现了这个问题: ERROR: You need to specify a debugger program in the debuggers' ...
- Micropython TurnipBit 青少年入门编程 交通灯实验
不知道大家小时候对红绿灯的原理有什么研究过,我是农村的孩子直到初中才见到真实的红绿灯,当时我记得很清楚,在那个路口站了五六分钟就盯着红绿灯变换,搞不清原理,只觉得神奇.现在想来实在可笑,今天写这个的很 ...