Flask表单

表单

在web程序中,表单是与用户交互的最常见的方式之一。用户注册、登录、撰写文章。不过,表单的处理却并不简单。你不仅要创建表单,验证用户输入的内容,向用户显示错误提示,还要获取并保存数据。幸运的是,强大的WTForms可以帮我们解决这些问题。WTForms是一个使用Python编写的表单库,它使得表单的定义、验证(服务器端)和处理变得非常轻松。这一章我们会介绍在Web程序中处理表单的方法和技巧。

4.1HTML表单

<form method="post"> # 表单
    <label for="username">Username</label><br>
    <input type="text" name="username" placeholder="Héctor Rivera"><br>   # 输入字段
    <label for="password">Password</label><br>
    <input type="password" name="password" placeholder="19001130"><br>
    <input id="remember" name="remember" type="checkbox" checked>
    <label for="remember"><small>Remember me</small></label><br>
    <input type="submit" name="submit" value="Log in">  # 提交
</form>

<label>标签则用来定义字段的标签文字。我们可以在<form><input>标签中使用各种属性来对表单进行设置。上面的表单被浏览器解析后会生成两个输入框,一个勾选框和一个提交按钮。
WTForms支持在Python中使用类定义表单,然后直接通过类定义生成对应的HTML代码,这种方式更加方便,而且使表单更易于重用。因此,除非是非常简单的程序,或者是你想让表单的定义更加灵活,否则我们一般不会在模板中直接使用HTML编写表单,

4.2使用Flask-WTF处理表单

扩展Flask-WTF集成了WTForms,使用它可以在Flask中更方便地使用WTFroms。Flask-WTF将表单数据解析、CSRF保护、文件上传等功能与Flask集成,另外还附加reCAPTCHA支持(google验证码服务)。
Flask-WTF默认为每个表单启用CSRF保护,它会为我们自动生成和验证CSRF令牌。默认情况下,Flask-WTF使用程序密钥来对CSRF令牌进行签名,所以我们需要为程序设置密钥:app.secret_key='secret string'

4.2.1定义WTForms表单类

表单由Python类表示,这个类继承从WTForms导入的Form基类。from wtforms import Form, StringField, PasswordField, BooleanField, SubmitField。字段分别用表单类的类属性来表示。
随意定一个类:

 class LoginForm(Form):
...     username = StringField('Username', validators=[DataRequired()])
...     password = PasswordField('Password', validators=[DataRequired(), Length(8, 128)])
...     remember = BooleanField('Remember me')
...     submit = SubmitField('Log in')

这里的LoginForm表单类中定义了四个字段:文本字段StringField、密码字段Password Field、勾选框字段BooleanField和提交按钮字段SubmitField。字段类从wtforms包导入。
常用字段:
Flask表单
通过实例化字段类时传入的参数,我们可以对字段进行设置,字段类构造方法接收的常用参数:
Flask表单
WTForms中,验证器(validator)是一系列用于验证字段数据的类,我们在实例化字段类时使用validators关键字来指定附加的验证器列表。验证器从wtforms.validators模块中导入,常用的验证器:
Flask表单
Flask表单

4.2.2输出HTML代码

类定义的表单如何输出HTML代码的。

>>> form = LoginForm()
>>> form.username()
u'<input id="username" name="username" type="text" value="">'
>>> form.submit()
u'<input id="submit" name="submit" type="submit" value="Submit">'
>>> form.username.label()
u'<label for="username">Username</label>'
>>> form.submit.label()
u'<label for="submit">Submit</label>'

4.2.3在模板中渲染表单

使用render_temple()函数中使用关键字参数form将表单实例传入模板。

from forms import LoginForm
@app.route('/basic')
def basic():
    form = LoginForm()
    return render_template('basic.html', form=form)

在模板中,只需要调用表单类的属性即可获取字段对应的HTML代码,如果需要传入参数,也可以添加括号,如:

<form method="post">
    {{ form.csrf_token }} <!-- 渲染CSRF令牌隐藏字段 -->
    {{ form.username.label }}<br>{{ form.username }}<br>
    {{ form.password.label }}<br>{{ form.password }}<br>
    {{ form.remember }}{{ form.remember.label }}<br>
    {{ form.submit }}<br>
</form>

form.csrf_token字段包含了自动生成的CSRF令牌值,在提交表单后会自动被验证,为了确保表单通过验证,我们必须在表单中手动渲染这个字段(Flask-WTF为表单类实例提供了一个form.hidden_tag()方法,这个方法会依次渲染表单中所有的隐藏字段。因为csrf_token字段也是隐藏字段,所以当这个方法被调用时也会渲染csrf_token字段。
渲染后实际效果:

<form method="post">
    <input id="csrf_token" name="csrf_token" type="hidden" value="IjVmMDE1ZmFjM2VjYmZjY...i.DY1QSg.IWc1WEWxr3TvmAWCTHRMGjIcDOQ">
    <label for="username">Username</label><br>
    <input id="username" name="username" type="text" value=""><br>
    <label for="password">Password</label><br>
    <input id="password" name="password" type="password" value=""><br>
    <input id="remember" name="remember" type="checkbox" value="y"><label for="remember">Remember me</label><br>
    <input id="submit" name="submit" type="submit" value="Log in"><br>
</form>

4.3表单处理

表单数据的处理涉及很多内容,除去表单提交不说,从获取数据到保存数据大致会经历以下步骤:
1)解析请求,获取表单数据。
2)对数据进行必要的转换,比如将勾选框的值转换成Python的布尔值。
3)验证数据是否符合要求,同时验证CSRF令牌。
4)如果验证未通过则需要生成错误消息,并在模板中显示错误消息。
5)如果通过验证,就把数据保存到数据库或做进一步处理。
除非是简单的程序,否则手动处理不太现实,使用Flask-WTF和WTForms可以极大地简化这些步骤。

4.3.1提交表单

提交表单时,就会创建一个表单的HTTP请求,请求中包含表单各个字段的数据。表单的提交行为主要由三个属性控制:
Flask表单

上一篇:python – WTForms支持输入readonly属性?


下一篇:python – WTForms创建自定义小部件