flask-wtf 是专门用来处理web表单的插件,它可以减少你在前端的工作量,简化你在后端处理post表单请求时的工作,能够自动对前端提交的form数据做验证。
安装方法如下
pip install flask-WTF
本教程编写时使用的版本是flask-WTF-1.0.1
使用flask-wtf ,需要你根据表单定义Form类, 我以登录为例
class LoginForm(FlaskForm):
username = StringField('username')
password = PasswordField('password')
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login", method="post">
{{ form.csrf_token }}
{{ form.username.label }} {{ form.username(size=20) }}
{{ form.password.label }} {{ form.password(size=20) }}
<input type="submit" value="登录">
</form>
</body>
</html>
在form表单里,我并没有编写类似下面的代码
<label for="username">username</label> <input id="username" name="username" size="20" type="text" value="">
这样的代码,flask在渲染时会根据我所定义的LoginForm 自动生成,这样就减少了前端的一部分工作量,对于专业的前端来说,他可能更喜欢自己写标签,但如果你是全栈工程师,wtf还是能帮到你的。
在编写一个首页,index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p> 欢迎你 {{ username }}</p>
</body>
</html>
用户登录成功以后,将显示登录者的username
@app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.password.data == "123456":
response = redirect('/index')
response.set_cookie('username', form.username.data )
return response
return render_template("login.html", form=form)
validate_on_submit 会判断请求是否是POST方法,以及提交的表单是否正确,验证逻辑,我只比较password是否等于123456, 然后将username 设置到cookie里,随后跳转到首页
from flask import Flask, render_template, request, redirect
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
class LoginForm(FlaskForm):
username = StringField('username')
password = PasswordField('password')
app = Flask(__name__)
app.secret_key = "hard to guess"
@app.route('/index')
def index():
username = request.cookies.get("username", '')
return render_template('index.html', username=username)
@app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.password.data == "123456":
response = redirect('/index')
response.set_cookie('username', form.username.data )
return response
return render_template("login.html", form=form)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5500)
在前端页面的表单里,我添加了csrf_token, 这是为了防止跨站请求伪造。
在第二节的例子里,并没有对post所提交的表单进行字段正确性检查,flask-wtf 允许你为一个字段指定多个validator进行检查。
常用的验证器有:
除了模块自身提供的验证器,还可以自定义验证器
from flask import Flask, render_template, request, redirect, flash
from flask_wtf import FlaskForm
from wtforms.validators import InputRequired, ValidationError
from wtforms import StringField, PasswordField
def password_check(form, field):
if len(field.data) != 6:
raise ValidationError('密码必须是6位')
class LoginForm(FlaskForm):
username = StringField('username', validators=[InputRequired()])
password = PasswordField('password', validators=[InputRequired(), password_check])
自定义验证器必须接收两个参数,分别是form和field, 验证器不通过时,可以通过form.errors 来获取不通过的原因
@app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.password.data == "123456":
response = redirect('/index')
response.set_cookie('username', form.username.data )
return response
else:
if request.method == "POST":
errors = form.errors # 表单验证不通过的原因
print(errors)
flash(str(errors))
return render_template("login.html", form=form)
验证错误,我简单的通过flash传递给前端页面,前端页面也稍作修改, login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</head>
<body>
<form action="/login", method="post">
{{ form.csrf_token }}
{{ form.username.label }} {{ form.username(size=20) }}
{{ form.password.label }} {{ form.password(size=20) }}
<input type="submit" value="登录">
</form>
</body>
</html>
启动服务进入登录页面,这一次,某个字段如果没有填写,前端页面就会提示你必须填写,如果密码长度不符合要求,会在前端页面里显示出错误原因。
QQ交流群: 211426309