Flask - WTF和WTForms创建表单
Flask - WTF和WTForms创建表单
一. Flask-WTF
Flask-WTF是集成WTForms,并带有 csrf 令牌的安全表单和全局的 csrf 保护的功能。
每次我们在建立表单所创建的类都是继承与flask_wtf中的FlaskForm,而FlaskForm是继承WTForms中forms。
1.创建基础表单
class LoginForm(FlaskForm):
username = StringField()
password = PasswordField()
remember_me = BooleanField(label='Keep me logged in')
2.CSRF保护
任何使用FlaskForm创建的表单发送请求,都会有CSRF的全部保护,在对应的template中HTML渲染表单时,可以加入form.csrf_token:
<form method="post">
{{ form.csrf_token }}
</form>
但是如果模板中没有表单,则可以使用一个隐藏的input标签加入csrf_token。
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
3.验证表单
在视图处理程序中验证请求:
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('login.html', form=form)
# 使用validate_on_submit 来检查是否是一个 POST 请求并且请求是否有效。
或者下面这种方式:
new_lf = LoginForm(formdata=request.form)
if new_lf.validate():
return "登陆成功"
else:
return render_template("login.html", lf=new_lf)
4.文件上传
Flask-WTF 提供 FileField 来处理文件上传,它在表单提交后,自动从 flask.request.files 中抽取数据。FileField 的 data 属性是一个 Werkzeug FileStorage 实例。
from werkzeug import secure_filename
from flask_wtf.file import FileField
class PhotoForm(Form):
photo = FileField('Your photo')
@app.route('/upload/', methods=('GET', 'POST'))
def upload():
form = PhotoForm()
if form.validate_on_submit():
filename = secure_filename(form.photo.data.filename)
form.photo.data.save('uploads/' + filename)
else:
filename = None
return render_template('upload.html', form=form, filename=filename)
注意:在 HTML 表单的 enctype 设置成 multipart/form-data,如下:
5.验证码
Flask-WTF 通过 RecaptchaField 也提供对验证码的支持:
rom flask_wtf import Form, RecaptchaField
from wtforms import TextField
class SignupForm(Form):
username = TextField('Username')
recaptcha = RecaptchaField()
还需要配置一下信息:
# 字段 # 配置
RECAPTCHA_PUBLIC_KEY # 必须公钥
RECAPTCHA_PRIVATE_KEY # 必须私钥
RECAPTCHA_API_SERVER # 可选验证码API服务器
RECAPTCHA_PARAMETERS # 可选 一个 JavaScript(api.js)参数的字典
RECAPTCHA_DATA_ATTRS # 可选 一个数据属性项列表 https://developers.google.com/recaptcha/docs/display
二. WTForms
WTForms是一个Flask集成的框架,或者是说库。用于处理浏览器表单提交的数据。它在Flask-WTF 的基础上扩展并添加了一些随手即得的精巧的帮助函数,这些函数将会使在 Flask 里使用表单更加有趣。
1. field字段
WTForms支持HTML字段:
字段类型: 说明:
StringFidle 文本字段, 相当于type类型为text的input标签
TextAreaField 多行文本字段
PasswordField 密码文本字段
HiddenField 隐藏文本字段
DateField 文本字段, 值为datetime.date格式
DateTimeFieeld 文本字段, 值为datetime.datetime格式
IntegerField 文本字段, 值为整数
DecimalField 文本字段, 值为decimal.Decimal
FloatField 文本字段, 值为浮点数
BooleanField 复选框, 值为True 和 False
RadioField 一组单选框
SelectField 下拉列表
SelectMultipleField 下拉列表, 可选择多个值
FileField 文件上传字段
SubmitField 表单提交按钮
FormFiled 把表单作为字段嵌入另一个表单
FieldList 子组指定类型的字段
2.Validators验证器
WTForms可以支持很多表单的验证函数:
Email
验证是电子邮件地址
EqualTo
比较两个字段的值; 常用于要求输入两次密钥进行确认的情况
IPAddress
验证IPv4网络地址
Length
验证输入字符串的长度
NumberRange
验证输入的值在数字范围内
Optional
无输入值时跳过其它验证函数
DataRequired
确保字段中有数据
Regexp
使用正则表达式验证输入值
URL
验证url
AnyOf
确保输入值在可选值列表中
NoneOf
确保输入值不在可选列表中
3.自定义Validators验证器
第一种: in-line validator(内联验证器)
也就是自定义一个验证函数,在定义表单类的时候,在对应的字段中加入该函数进行认证。下面的my_length_check函数就是用于判name字段长度不能超过50.
def my_length_check(form, field):
if len(field.data) > 50:
raise ValidationError('Field must be less than 50 characters')
class MyForm(Form):
name = StringField('Name', [InputRequired(), my_length_check])
第二种:通用且可重用的验证函数
一般是以validate开头,加上下划线再加上对应的field字段(validate_filed),浏览器在提交表单数据时,会自动识别对应字段所有的验证器,然后执行验证器进行判断。
class RegistrationForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(1, 60), Email()])
username = StringField('Username', validators=[DataRequired(), Length(1, 60),
Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0, 'username must have only letters, numbers dots or underscores')])
password = PasswordField('Password', validators=[DataRequired(), EqualTo('password2', message='password must match')])
password2 = PasswordField('Confirm password', validators=[DataRequired()])
def validate_email(self, field):
if User.objects.filter(email=field.data).count() > 0:
raise ValidationError('Email already registered')
def validate_username(self, field):
if User.objects.filter(username=field.data).count() > 0:
raise ValidationError('Username has exist')
第三种:比较高级的validators
class Length(object):
def __init__(self, min=-1, max=-1, message=None):
self.min = min
self.max = max
if not message:
message = u'Field must be between %i and %i characters long.' % (min, max)
self.message = message
def __call__(self, form, field):
l = field.data and len(field.data) or 0
if l < self.min or self.max != -1 and l > self.max:
raise ValidationError(self.message)
length = Length
4.Widget组件
下面可以以登录界面为实例:
login.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms import validators
from wtforms import widgets
class LoginForm(Form):
name = simple.StringField(
label='用户名',
validators=[
validators.DataRequired(message='用户名不能为空.'),
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'}
)
pwd = simple.PasswordField(
label='密码',
validators=[
validators.DataRequired(message='密码不能为空.'),
],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
)
三. 简单的登录验证表单实例
from flask import Flask, request, render_template, redirect
from wtforms.fields import simple, core
from wtforms import Form, validators
app = Flask(__name__)
app.config["DEBUG"] = True
class LoginForm(Form):
username = simple.StringField(
label="用户名:",
validators=[
validators.DataRequired(message="用户名不能为空"),
validators.Length(min=4, max=10, message="用户名不能小于%(min)d,不能大于%(max)d")
], # 声明校验方式
id="username",
# widget=widgets.FileInput(),
render_kw={"class": "my_class"},
)
password = simple.PasswordField(
label="密码:",
validators=[
validators.Length(max=10, min=6, message="password不能小于%(min)d,不能大于%(max)d"),
validators.Regexp("\d+", message="密码只能是数字")
],
id="pwd",
render_kw={"style": "width:300px;"}
)
sub = simple.SubmitField(
label="登陆",
render_kw={"class": "bs"}
)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "GET":
lf = LoginForm()
return render_template("login.html", lf=lf)
else:
new_lf = LoginForm(formdata=request.form)
if new_lf.validate():
return "登陆成功"
else:
return render_template("login.html", lf=new_lf)
class RegForm(Form):
username = simple.StringField(
label="用户名:",
validators=[
validators.Length(min=4, max=10, message="用户名不能小于%(min)d,不能大于%(max)d")
]
)
password = simple.PasswordField(
label="密码:",
validators=[
validators.Length(max=10, min=6, message="password不能小于%(min)d,不能大于%(max)d")
]
)
repassword = simple.PasswordField(
label="确认眼神:",
validators=[
validators.EqualTo("password", message="眼神未确认")
]
)
email = simple.StringField(
label="邮箱",
validators=[
validators.Email(message="邮箱格式不符")
]
)
gender = core.RadioField(
label="性别:",
choices=[
(1, "女"),
(2, "男")
],
coerce=int
)
hobby = core.SelectMultipleField(
label="嗜好",
choices=[
(1, "小姐姐"),
(2, "小萝莉"),
(3, "小正太"),
(4, "小哥哥")
],
coerce=int
)
sub = simple.SubmitField(
label="登陆",
render_kw={"class": "bs"}
)
@app.route("/reg", methods=["GET", "POST"])
def reg():
if request.method == "GET":
regf = RegForm()
return render_template("reg.html", regf=regf)
else:
new_regf = RegForm(formdata=request.form)
if new_regf.validate():
print(new_regf.data.get("gender"))
print(new_regf.data.get("hobby"))
return new_regf.data.get("username")
else:
return render_template("reg.html", regf=new_regf)
if __name__ == '__main__':
app.run()
参考链接:
1.https://wtforms.readthedocs.io/en/stable/
2.https://flask-wtf.readthedocs.io/en/stable/
Flask - WTF和WTForms创建表单的更多相关文章
- Flask开发系列之Web表单
Flask开发系列之Web表单 简单示例 from flask import Flask, request, render_template app = Flask(__name__) @app.ro ...
- flask插件系列之Flask-WTF表单
flask_wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具,支持热插拔. 安装 pip install Flask-WTF Flask-WTF其实是对w ...
- 使用 WTForms 进行表单验证的例子
#使用 WTForms 进行表单验证的例子 from wtforms import Form from wtforms import BooleanField from wtforms import ...
- flask实战-个人博客-表单
表单 下面我们来编写所有表单类,personalBlog中主要包含下面这些表单: 登录表单: 文章表单: 评论表单: 博客设置表单: 这里仅介绍登录表单.文章表单.分类表单和评论表单,其他的表单在实现 ...
- 在火狐、360等浏览器中,用jquery创建表单并发送的问题
某些浏览器无法使用js或者jquery直接创建表单并发送,这是由于这些浏览器在提交页面表单时要求页面有完整的标签项即<html><head><title></ ...
- SPC2014 :“FOSL”不是替代InfoPath,只是另外一种创建表单的方式
今天在SPC2014微软宣布他们技术路线图.其实,没有足够证据替代InfoPath,只是另外的一种尝试 - FOSL(对SharePoint列表表单). FOSL使用相同的引擎,用于创建表单的访问服务 ...
- activiti自定义流程之整合(二):使用angular js整合ueditor创建表单
注:整体环境搭建:activiti自定义流程之整合(一):整体环境配置 基础环境搭建完毕,接下来就该正式着手代码编写了,在说代码之前,我觉得有必要先说明一下activit自定义流程的操作. 抛开自定义 ...
- activiti自定义流程之自定义表单(二):创建表单
注:环境配置:activiti自定义流程之自定义表单(一):环境配置 在上一节自定义表单环境搭建好以后,我就正式开始尝试自己创建表单,在后台的处理就比较常规,主要是针对ueditor插件的功能在前端进 ...
- 【LABVIEW到C#】2》database的操作(一)之 创建access和创建表单
namespace添加如下 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
随机推荐
- BeautifulSoup中各种html解析器的比較及使用
Beautiful Soup解析器比較 ·Beautiful Soup支持各种html解析器.包含python自带的标准库.还有其它的很多第三方库模块. 当中一个就是lxml parser,至于lxm ...
- 【转】Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法
重构了下之前自己的一个新闻客户端,全部使用了Fragment来进行页面切换,只有一个入口Activity作为程序的启动Activity,其中有一个界面需要调用摄像头识别二维码, 于是就会用到Surfa ...
- bzoj 1601 灌水
题目大意: 决定把水灌到n块农田,农田被数字1到n标记 把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库 建造一个水库需要花费wi,连接两块土地需要花费Pij. 计算所需的最少代价 ...
- 【POJ 3190】 Stall Reservations
[题目链接] http://poj.org/problem?id=3190 [算法] 将这些牛按开始吃草的时间排序 维护一个数组S,Si表示畜栏i进去的最后一头牛结束吃草的时间,对于每头牛,找任意一个 ...
- Spring-Security-OAuth2微信网页授权
@Controller public class Controller1 { @Autowired private OAuth2ClientContext context; @Bean @Scope( ...
- PHP 在线 编辑 解析
http://www.w3schools.com/php/default.asp http://www.w3schools.com/php/showphp.asp?filename=demo_s ...
- Linq学习(二)-本次学习用到的资料
本次学习用到的数据库初始化脚本如下 use KMS create table Blog_User ( UserId ,1), NickName ), CreateTime datetime ) cre ...
- fresh_bank、、
最近新学习了一个bank系统来和大家分享一下,新人求罩! 破索式之_链子枪_ 废话不多说了直接本主题 如果我们要写出bank系统,就要先考虑这个问题:总共需要几个类? 既然是银行系统,那么必不可少的就 ...
- 【转】Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
概要 前面,我们学完了List的全部内容(ArrayList, LinkedList, Vector, Stack). Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例 Ja ...
- Active Learning主动学习
Active Learning主动学习 我们使用一些传统的监督学习方法做分类的时候,往往是训练样本规模越大,分类的效果就越好.但是在现实生活的很多场景中,标记样本的获取是比较困难的,这需要领域内的专家 ...