Flask 中的表单操作可以通过 Flask-WTF 这个扩展来实现
安装
pip install flask-wtf
跨站请求保护
默认情况下,Flask-WTF 能保护所有表单免受跨站请求伪造( CSRF )的攻击,恶意网站把请求发送到被攻击者已登录的其他网站就会引发 CSRF 攻击。为了实现 CSRF 保护,Flask-WTF 需要程序设置一个秘钥,Flask-WTF 使用这个秘钥生成加密令牌,再用这个令牌验证表单数据的真伪。所以第一步,我们需要设置一个秘钥。
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config 字典可用来存储框架,扩展,程序本身的配置变量,使用标准的字典语句就能进行配置。注意,为了安全性,秘钥是不应该直接写在代码中的,而应该设置在环境变量中,这里仅仅作为一个示范。
定义一个表单类
使用 Flask-WTF 时,每一个 web 表单都由一个继承自 Form( FlaskForm ) 的类表示
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
app = Flask(__name__)
class Form(FlaskForm):
name = StringField('What is your name?', validators=[DataRequired()])
submit = SubmitField('Submit')
表单中的字段都定义为类变量,类变量的值是相应字段类型的对象。像上面这个例子,就有一个名为 name 的文本字段,和一个名为 submit 的提交按钮。其中 StringField 构造函数中可选参数 validators 指定一个由验证函数组成的列表,在接受用户提交的数据之前验证数据,例子中的是确保提交字段不为空,下面给出具体字段及说明。
WTForms 支持的 html 标准字段
字段类型 | 说 明 |
---|---|
StringField | 文本字段 |
TextAreaField | 多行文本字段 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
DateField | 文本字段,值为 datetime.date 格式 |
DateTimeField | 文本字段,值为 datetime.datetime 格式 |
IntegerField | 文本字段,值为整数 |
DecimalField | 文本字段,值为 decimal.Decimal |
FloatField | 文本字段,值为浮点数 |
BooleanField | 复选框,值为 True 和 False |
RadioField | 一组单选框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表,可选择多个值 |
FileField | 文件上传字段 |
SubmitField | 表单提交按钮 |
FormField | 把表单作为字段嵌入另一个表单 |
FieldList | 一组指定类型的字段 |
WTForms 验证函数
验证函数 | 说 明 |
---|---|
验证电子邮件地址 | |
EqualTo | 比较两个字段的值;常用于要求输入两次密码进行确认的情况 |
IPAddress | 验证 IPv4 网络地址 |
Length | 验证输入字符串的长度 |
NumberRange | 验证输入的值在数字范围内 |
Optional | 无输入值时跳过其他验证函数 |
Required | 确保字段中有数据 |
Regexp | 使用正则表达式验证输入值 |
URL | 验证 URL |
AnyOf | 确保输入值在可选值列表中 |
NoneOf | 确保输入值不在可选值列表中 |
模板生成表单
<form method="post">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
这是一个简单的表单,只包含一个 name 和 提交按钮,接下来看一个完整的范例:
这是我的视图函数以及表单类,视图函数中响应的 home.html 就是刚刚给出的简易表单,路由注册时,记得将其注册为 get 和 post 处理程序,响应的时候,将实例化的对象 form 通过参数 form 传给前端,一起来看一下效果。
这里为了明显看出结果,我在视图函数中,将接收到的 form 的 name 字段打印出来了,也就是 “hello world”
使用现有的 html 表单
当然,你也可以选择不使用 WTForms 的表单,而使用自己写的 html 表单,for example:
<html>
<head></head>
<body>
<div align="center">
<h1>User Manage</h1>
{% if message %} {{ message }} {% endif %} <!--用于提示错误信息 -->
<form method="post">
<input type="text" name="username" placeholder="username"/>
<br/>
<input type="password" name="password" placeholder="password"/>
<br/>
<input type="submit">
<input type="reset">
</form>
</div>
</body>
</html>
这是写好的 html 表单
from flask import Flask,render_template,redirect,request
app = Flask(__name__)
@app.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username == 'root' and password == 'root':
return redirect('http://www.baidu.com')
else:
message = 'login faild'
return render_template('base.html', message=message)
return render_template('base.html')
if __name__ == '__main__':
app.run()
这是 Python 的处理代码,判断用户名和密码是否正确,正确的话则跳转到百度首,html 界面和后台的视图函数间,通过 request 来传递数据,是不是非常方便。