flask表单

WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。
还包含了一些其他功能:CSRF保护、文件上传等。

使用wtforms的好处是:

  • form验证可以使用python来做, 不必将验证代码放到javascript中.
  • 在python视图函数中, 可以很方便地获取表单元素, 比如使用form.username.data, 即可获取表单上的username值.
  • 可以简化html模板的设计. 采用Flask-Bootstrap 扩展或者使用一些jinja2 marco都能简化html代码.
  • 更重要的好处是, 将validation逻辑从表现层中解耦

表单验证

定义表单类

  • 表单类必须继承自wtforms.Form,定义需要验证的字段,字段的名字必须和模板中需要验证的input标签的name属性相同

  • 在需要验证的字段上,需要指定好具体的数据类型
    WTForms支持的HTML标准字段:

    字段类型 说明
    StringField 文本字段, 相当于type类型为text的input标签
    TextAreaField 多行文本字段
    PasswordField 密码文本字段
    HiddenField 隐藏文本字段
    DateField 文本字段, 值为datetime.date格式
    DateTimeField 文本字段, 值为datetime.datetime格式
    IntegerField 文本字段, 值为整数
    DecimalField 文本字段, 值为decimal.Decimal
    FloatField 文本字段, 值为浮点数
    BooleanField 复选框, 值为True 和 False
    RadioField 一组单选框
    SelectField 下拉列表
    SelectMultipleField 下拉列表, 可选择多个值
    FileField 文件上传字段
    SubmitField 表单提交按钮
    FormFiled 把表单作为字段嵌入另一个表单
    FieldList 子组指定类型的字段
  • 在相关的字段上指定验证器
    常用验证器:

    验证器 描述
    Email 验证上传的数据是否为邮箱
    EqualTo 验证上传的数据是否和另一个字段相等
    InputRequaired 原值数据的需要验证
    Length 长度限制,有min和max两个值进行限制
    NumberRange 数字的区间,有min和max两个值限制
    Regexp 自定义正则表达式
    URL 必须要是URL格式
    IPAddress 验证上传的数据是否为IP地址
    UUID 验证UUID
    AnyOf 确保输入值在可选值列表中
    NoneOf 确保输入值不在可选列表中

    自定义验证器:
    在定义的表单类中定义名为validate_<想要验证的变量名>的方法即可。

    1
    2
    3
    def validate_password(self, field):            # fileld为要验证的变量的field 
    if fileld.data != "password": # field.data为用户输入的内容
    raise ValidationError("密码输入错误") # 不满足验证器,抛出异常
  • 一个例子
    表单类:

    1
    2
    3
    4
    5
    6
    7
    from wtforms import Form, StringField
    from wtforms.validators import Length, EqualTo

    class RegisterForm(Form):
    username = StringField(validators=[Length(min=3, max=10, message="用户名长度必须在3-10位之间")])
    password = StringField(validators=[Length(min=6, max=20, message="密码长度必须在6-20位之间")])
    password_repeat = StringField(validators=[Length(min=6, max=20, message="密码长度必须在6-20位之间"), EqualTo("password", message="两次输入的密码不同")])

    html表单模板:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <form action="" method="POST">
    <table>
    <tr>
    <td>用户名:</td>
    <td><input type="text" name="username"></td>
    </tr>
    <tr>
    <td>密码:</td>
    <td><input type="password" name="password"></td>
    </tr>
    <tr>
    <td>重复密码:</td>
    <td><input type="password" name="password_repeat"></td>
    </tr>
    <tr>
    <td><input type="submit" value="注册"></td>
    </tr>
    </table>
    </form>

在视图函数中使用

在实例化表单类的时候要传入需要验证的数据,通常使用request.form

1
form = RegisterForm(request.form)

之后可以使用form.validate()来判断传入的数据是否通过验证,如果通过验证则返回True

1
2
3
4
if form.validate():
return "success"
else:
return "fail"

对于没有通过验证的表单条列,可以通过form.条列名.errors获取,获取的错误信息可以在条目的message参数中设置。
可以使用render_template的form参数来传入表单对象,用来渲染html模板。

视图函数:

1
2
3
4
5
6
7
8
9
10
@app.route("/register/", endpoint="register", methods=["GET", "POST"])
def register():
form = RegisterForm(request.form)
if request.method == "GET":
return render_template("register.html", form=form)
else:
if form.validate():
return "success"
else:
return render_template("register.html", form=form)

html模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<form action="" method="POST">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
<td>
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
<td>
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td>重复密码:</td>
<td><input type="password" name="password_repeat"></td>
<td>
{% for error in form.password_repeat.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</td>
</tr>
<tr>
<td><input type="submit" value="注册"></td>
</tr>
</table>
</form>
文章作者: Dar1in9
文章链接: http://dar1in9s.github.io/2020/03/10/flask/flask表单/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dar1in9's Blog