使用 Flask-WTF 接收和验证表单参数
简介
WTForms 是支持多个 Web 框架的表单库,主要用于验证用户请求数据。Flask-WTF 集成 WTForms,并自带 CSRF 令牌保护和全局 CSRF 防护。
安装
python -m pip install Flask-WTF
定义表单类
forms.py:
from flask_wtf import FlaskForm
from wtforms import (
IntegerField,
PasswordField,
StringField,
SubmitField,
ValidationError,
)
from wtforms.validators import (
DataRequired,
EqualTo,
Length,
NumberRange,
Regexp,
)
class UserInfoForm(FlaskForm):
username = StringField("用户名", validators=[DataRequired(), Length(min=2, max=20)])
password = PasswordField(
"密码", validators=[DataRequired(), Length(min=6, max=20)]
)
password_repeat = PasswordField(
"确认密码", validators=[EqualTo("password", message="两次密码不一致")]
)
age = IntegerField("年龄", validators=[NumberRange(min=1, max=150)])
mobile = StringField("手机号", validators=[Regexp(r"^1\d{10}$", message="手机号格式错误")])
user_status = StringField("状态")
submit = SubmitField("提交")
# 自定义校验器:validate_字段名 会在该字段校验时自动调用
def validate_username(self, field):
if field.data == "admin":
raise ValidationError("该用户名已被占用")
应用中使用
app.py:
from flask import Flask, redirect, render_template, request
from forms import UserInfoForm
app = Flask(__name__)
app.config["SECRET_KEY"] = "1234567890" # CSRF 校验需要 secret_key
@app.get("/")
def root():
return "this is root"
@app.route("/userinfo", methods=["GET", "POST"])
def userinfo():
form = UserInfoForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
print(f"form username: {username}, password: {password}")
return redirect("/")
return render_template("userinfo.html", form=form)
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
form.validate_on_submit()会同时校验请求方法(POST)和 CSRF 令牌;验证失败时错误信息写入form.errors。
templates/userinfo.html:
<html>
<body>
<form action="" method="POST" novalidate>
{{ form.csrf_token }}
<p>{{ form.username.label }}: {{ form.username }} {{ form.username.errors[0] }}</p>
<p>{{ form.password.label }}: {{ form.password }} {{ form.password.errors[0] }}</p>
<p>{{ form.password_repeat.label }}: {{ form.password_repeat }} {{ form.password_repeat.errors[0] }}</p>
<p>{{ form.age.label }}: {{ form.age }} {{ form.age.errors[0] }}</p>
<p>{{ form.mobile.label }}: {{ form.mobile }} {{ form.mobile.errors[0] }}</p>
<p>{{ form.user_status.label }}: {{ form.user_status }} {{ form.user_status.errors[0] }}</p>
{{ form.submit() }}
<br>
错误信息汇总:<br>
{% for k in form.errors %}
{{ form.errors[k][0] }}<br>
{% endfor %}
</form>
</body>
</html>