这部分由于没有记在笔记里所以我将它放在博客里。
因为Flask框架是一个轻量级的框架,许多拓展功能都不在最基础里的包里,因此需要安装第三方模块。处理表单及验证表单都需要下载一个叫做Flask-WTF的模块。下载它很简单,只需要使用pip install flask-wtf
即可。下载完此模块后该模块的附带模块WTForms也会一并安装。
处理CSRF
CSRF,全称为跨站请求伪造,为了防止这种攻击,在每次表单提交时都会附带一个独一无二的token。这个token在表单被验证之前先被验证。为了生成这个token,实现对表单的保护,一般需要为程序设置一个密钥。设置密钥的语法如下:
python 代码:app = Flask(__name__)
app.config['SECERT_KEY'] = 'qi1.zone'
app.config用于配置Flask,通过SECRET_KEY配置的密钥,对整个Flask应用以及很多拓展应用都是有效的。
表单类
使用Flask-WTF时,每一个表单都是由一个继承自Form的类表示,这个类定义了表单的字段,每个字段都由一个对象表示。字段对象可附属一个或多个验证函数,用来验证字段值是否符合要求。如下面的代码:
python 代码:from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
class NameForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
submit = Submit('提交')
首先导入必要的包,其中FlaskForm就是Flask表单类,我们所要使用的表单需要继承自这个类;StringField等就是字段类,这个表单我们共有三个字段:姓名,密码和提交,因此我们用到了对应的三个字段对象;最后就是验证函数,WTForms已经为我们预设好了一些基础的验证函数,这里我们选择字段必填,则应该使用DataRequired。然后就是自定义一个表单类继承自FlaskForm类,然后定义其中的成员变量,这些成员变量在表单被渲染后就会编程HTML代码中的各个字段。拿第一行来说,StringField就代表这个字段是普通文本行,第一个参数代表这个字段被渲染成HTML后那个输入框的标号,第二个参数为可选参数,即验证器。WTforms还支持许多HTML标准字段,如下表所示:
字段类型 | 说明 |
---|---|
StringField | 文本字段 |
TextAreaField | 多行文本字段 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
DateField | 文本字段,值为datatime.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 | 确保输入值在可选值列表中 |
HTML模板渲染方式
Flask框架使用Jinja2渲染模板,在模板中使用{{ variable }}
来输出变量,而Flask-WTF模块属于Flask框架的拓展模块,因此它也是支持使用Jinja2渲染的。在使用render_template渲染模板时,需要传入form参数,即表单,就是上方创建的表单对象。
在模板中,使用{{ form.field.label }}
展示标签,其中field是表单的字段对象,使用{{ form.field }}
展示具体字段。
下面是一个使用Flask-WTF和WTForms实现使用Flask渲染web表单的例子:
html 代码:<!--模板 login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
<!--首先需要加载token-->
{{ form.csrf_token }}
<!--左边是标签,右边是具体的字段 字段不需要加属性,Jinja2在渲染时会自动添加-->
{{ form.user.label }}:{{ form.user() }}<br/>
{{ form.password.label }}:{{ form.password() }}<br/>
{{ form.submit() }}
</form>
</body>
</html>
python 代码:# form.py
from flask_wtf import FlaskForm # 表单类
from wtforms import StringField, PasswordField, SubmitField # 导入字段对象
from wtforms.validators import DataRequired, Length # 导入验证器对象
class LoginForm(FlaskForm): # 创建自己的表单类,继承自biao'dan'lei
user = StringField(label='user', validators=[DataRequired('请输入用户名')]) # 实例化字段对象,第一个参数是标签,第二个参数是验证器
password = PasswordField(label='输入密码',
validators=[DataRequired('请输入密码'), Length(6, 16, '密码位数必须大于6小于16')])
submit = SubmitField(label='登录')
python 代码:#run.py
from flask import Flask, render_template, redirect, url_for
from form import LoginForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'qi1.zone' # 密钥
@app.route('/login', methods=['GET', 'POST']) # 注意请求方式要包含POST请求
def login():
form = LoginForm() # 实例化表单
if form.validate_on_submit(): # 若表单的数据都符合验证器的要求
user = form.user.data # 获取数据
password = form.password.data
if user == 'qi' and password == '123456': # 自己的判断条件
return '<h1>登录成功</h1>'
else:
return '登录失败'
# 同一缩进级别的if用于判断表单是否符合验证器的要求,若页面是第一次渲染则该方法返回false,就会跳到下方的代码,然后渲染模板
return render_template('login.html', form=form)
@app.route('/')
def index():
return redirect(url_for('login')) # 重定向
if __name__ == '__main__':
app.run(debug=True)
运行这段代码,浏览器输入URL,就可以看到登录页面,若账号密码均正确就会显示登录成功。同时若输入数据不符合要求则表单无法提交。