实施Flask WTForms
表单是Web应用程序不可或缺的组成部分。它们需要从用户那里发送数据到后台。在这篇文章中,我们将了解如何在我们的Flask网络应用中使用表单。
这篇文章需要对如何设置Flask网络应用程序有一个基本的了解。
配置工作环境
首先,将GitHub仓库克隆到你的环境中。
$ git clone https://github.com/corpsgeek/introduction-to-flask.git
把目录改成你拥有克隆的GitHub仓库的文件夹。继续安装克隆的Flask应用程序所需的必要包。
运行下面的命令来安装所需的依赖项。
$ pip3 install -r requirements.txt
注意,如果你运行的是Python2,那么用pip替换pip3。
可能出现的错误
如果你在安装克隆文件所需的依赖项时偶然发现以下错误,请忽略它,并继续进行下一步。
$ Could not find a version that satisfies the requirement pkg-resources==0.0.0 (from -r requirements.txt (line 6)) (from versions: )
No matching distribution found for pkg-resources==0.0.0 (from -r requirements.txt (line 6))
requirements.txt 文件夹中有一个Flask网络应用程序的pkg-resources==0.0.0 要求。这个资源是在克隆的资源库中使用虚拟环境的结果。虽然本文没有在虚拟环境下工作,但这导致了pkg-resources 的错误。
解决这个错误的另一个方法是,在安装项目所需的包之前,删除requirements.txt 文件中第6行的pkg-reources==0.0.0 要求。
运行应用程序
如果有任何不同于上述的错误,请评论,如果没有,请在终端执行以下内容,继续运行flask应用程序。
$ flask run
这样,你就可以进入你的网络浏览器,按照终端中的URL(127.0.0.1:500),你应该看到一个简单的hello world应用程序显示出来。

Flask中的表单处理
Flask框架没有提供独特的方式来处理表单。然而,存在两种开发人员可以创建和处理表单的方式。
表单创建技术
以下是Flask中创建表单的两种方法。
- HTML表单
- WTForms
表单处理技术
以下是Flask中处理表单的两种方法。
- 请求对象
- Flask-WTF扩展
使用HTML表单创建表单
在Flask应用程序中处理表单的第一步是在处理表单之前创建你的表单。你可以使用基本的HTML和CSS来创建你的表单。
然而,为了开发和生产的目的。使用Bootstrap等框架,因为Flask中的表单错误处理更容易。
在我们克隆的Flask应用程序中,HTML模板从app/views.py 文件中渲染出来,显示一个Hello World文本。现在,我们使用上述文件对应用程序进行编码。
然后在app文件夹中创建一个名为template的新文件夹。这个文件夹将包括我们所有的HTML文件。进一步创建一个名为register.html 的新HTML文件。
在register.html 文件夹中,我们用链接到Bootstrap CSS的完整HTML代码来初始化内容。
有了Bootstrap的register.html 文件的设置,你暂时不会使用任何Bootstrap类。
继续创建一个基本的HTML表单,接受用户名、电子邮件和密码。同时,确保你在表单标签中设置方法属性为post。
你应该有一个类似于此的东西。
<form action="" method="post">
<fieldset>
<label for="username">Username</label>
<input type="text" name="username" placeholder="username">
</fieldset>
<fieldset>
<label for="email"> Email</label>
<input type="email" name="email" placeholder="xyz@gmail.com">
</fieldset>
<fieldset>
<label for="password">Password</label>
<input type="password" name="password" placeholder="password">
</fieldset>
<button type="submit">Register</button>
</form>
渲染表单
为了渲染我们新创建的注册表单,我们导航到app文件夹内的view.py文件。
在我们的视图中,在app导入文件下面,让我们从Flask导入render_template 和request 函数。它们是渲染我们的HTML页面和发出请求所需要的。
from flask import render_template, request
创建注册路线
下一个过程是创建注册路由来处理表单。首先创建一个路径为/register 的路由和一个用于代码逻辑的注册函数。
在路由函数中,通过返回模板渲染registration.html 文件。返回render_template() 函数,并传入要渲染的HTML文件名。
你的代码应该类似于这样
@app.route("/register")
def register():
return render_template('register.html')
创建了表单和路由后,在你的网络浏览器中,按照URL导航到表单页面。127.0.0.1:500/path,其中你用你在路由中指定的路径名替换path 变量。
在我们的例子中,/register 是路径。如果你做得很好,那么你的网络浏览器应该显示这个。

处理表单数据
在这个阶段,你可以查看你的表单。试着像普通用户注册网络应用一样填写数据,然后点击提交按钮。通过提交数据,你应该看到一个405方法不允许的错误页面。这个错误可以按照这个过程来处理。
处理405方法错误
405方法不允许的错误告诉我们,页面的路由不接受我们在HTML表单中传递的方法。
解决这个问题的方法是切换到注册路由功能。在应用程序的路由装饰中,我们传入另一个参数,称为methods ,其中有一个路由应该期望的方法列表。
@app.route("/register", methods=["GET", "POST"])
def register():
return render_template('register.html')
在你的网页浏览器中,刷新页面。如果你在添加上述一行代码后仍然得到这个错误,说明Flask没有接收到这些变化,所以你必须杀死服务器并运行它,以使代码变化生效。
如果你刷新了你的页面并提交了用户数据,你会注意到你被转回了注册表单,这意味着你的表单数据被发送到了路由,但没有被处理。让我们继续用请求对象来处理这个表单数据。
请求对象
为了处理发送到我们路由的表单数据,我们使用请求对象。访问这个对象的方法是在你的路由文件中从Flask导入请求对象。
from flask import request
第一个过程是检查传入请求的方法,无论它是GET 请求还是POST 请求,处理这个问题的方法是使用请求对象的方法成员变量。
在你的register route函数中,我们检查请求方法是POST ,然后在if 块中,我们通过使用请求对象的form成员变量来获得发送的表单数据,然后传入HTML表单中每个字段的名称值,作为存储值的键。
@app.route("/register", methods=["GET", "POST"])
def register():
#check the request method to ensure the handling of POST request only
if request.method == "POST":
#store the form value
username = request.form["username"]
email = request.form["email"]
password = request.form["password"]
return render_template('register.html')
你的注册视图函数应该有一个类似的代码。回顾一下,传给request.form 方法的值是我们的HTML表单的名称值。
表单数据得到了充分的处理。下一个过程是将数据返回给网页,而不是将用户重定向到注册表单页面。
为了将数据返回到网页,请添加下面这行代码。
@app.route("/register", methods=["GET", "POST"])
def register():
#check the request method to ensure the handling of POST request only
if request.method == "POST":
#store the form value
username = request.form["username"]
email = request.form["email"]
password = request.form["password"]
return username + " <br/> " + email
return render_template('register.html')
通过在请求方法块内添加返回语句,Web应用程序将把用户重定向到一个空白页面,并显示他们的用户名数据。注意,你需要重新启动你的服务器以使代码的改变生效。
如果你已经按照说明进行了相应的操作,那么你应该能够使用请求对象来处理一个表单。现在,让我们继续进行另一种创建和处理表单的方法。
用Flask-WTForms创建表单
Flask WTForms是一个让表单处理变得简单和结构化的库。它还能确保有效地处理表单的渲染、验证和安全。
要用这种方法构建表单,首先要在我们的app目录下创建一个新文件,并将其命名为forms.py. 这个文件将包含所有的应用程序表单。让我们创建一个新的contact.html 模板,然后用路径/contact 的路由来处理表单逻辑,然后渲染联系模板。
在实现我们的flask表单的过程中,我们需要先安装Flask-WTForms 。
$ pip install flask-wtf
接下来,打开之前创建的forms.py 文件。
在这里,我们导入Flask表单。
from flask_wtf import FlaskForm
随后的步骤是创建一个联系表单。要做到这一点,我们要初始化一个继承了FlaskForm 对象的类。你的代码应该与此类似。
from flask_wtf import FlaskForm
class ContactForm(FlaskForm):
pass
接下来,我们继续创建我们的表单字段。一个联系表单最好由用户名、他们的电子邮件地址和一条信息组成。要在纯HTML中复制这一点,输入textfield和textarea将是唯一的选择。但是,这个过程与WTForms完全不同。
为了在WTForms中创建我们的表单字段,我们导入我们需要的字段。例如,用户的姓名字段将是一个字符串。因此,我们导入StringField 。
from wtforms import StringField
在导入StringField ,我们在我们的表单类中初始化了用户名的字段。
name = StringField('name', validators=[])
从上面的代码中,值得注意的是,WTForms中的字段接受两个参数。第一个是表单字段的标签和表单字段的验证器列表。由于我们需要用户提供这些数据,我们可以从Wtforms导入DataRequired() 验证器。
from wtforms.validator import DataRequired, Email
在验证器列表中,我们传入我们为特定字段要求的验证器。我将去创建电子邮件和消息字段,以避免使这篇文章变得臃肿。
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email
class ContactForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
email = StringField('email', validators=[DataRequired(), Email()])
message = TextAreaField('message', validators=[DataRequired()])
send = SubmitField('send')
这里唯一的新东西是,我导入了TextAreaField 和SubmitField ,来处理用户的信息和提交表单。有了这个,你的联系表单就完成了。现在让我们来渲染这个表单。
验证器的错误
当你运行你的Web应用程序时,如果缺少一个验证器包,请使用pip install ,安装验证器。例如,如果电子邮件验证器不可用,在你的终端运行以下程序来安装电子邮件验证器。
$ pip install email
渲染表单
为了渲染我们的表单,你需要做的第一件事是在你的app文件中为你的应用程序设置一个秘钥,也就是__init__.py 文件。
首先,我们需要为我们的秘钥生成一个随机的16位数的字符。做到这一点的安全方法是打开你的Python解释器,按照下面的编码过程。
Python 2.7.17 (default, Sep 30 2020, 13:38:04)
[GCC 7.5.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import secrets
>>> secrets.token_hex(16)
u'571ebf8e13ca209536c29be68d435c00'
>>>
引号中的字母数字字符是你需要复制来作为我们的__init__.py 文件中的秘钥,你可以通过添加以下内容来设置它。
from flask import Flask
app = Flask(__name__)
app.config["SECRET_KEY"] = '571ebf8e13ca209536c29be68d435c00'
from app import views
随后,在我们的路由文件中,我们声明了联系表单的路由函数,在我们的forms.py 文件中导入联系表单。
from app.forms import ContactForm
然后,在我们的视图函数中,我们创建一个表单的实例,然后将表单对象传递给我们的联系人模板。
@app.route("/contact", methods=["GET", "POST"])
def contact():
form = ContactForm()
return render_template('contact.html', form=form)
请进入我们的联系模板,在我们的浏览器中显示表单。用一个POST 方法初始化表单。
<form action="" method="post">
<!-- Form content -->
</form>
在我们的表单标签中,你需要做的第一件事是在表单的顶部添加以下标签。
{{ form.hidden_tag() }}
上面的Jinja代码添加了一个跨站请求伪造令牌,以保护我们的表单免受黑客的攻击。
接下来,我们要渲染表单标签和表单本身。为了做到这一点,我们利用jinja模板,而代码模板采取的是表单。
{{ form.varname_of_the_form_field.label()}}
{{ form.varname_of_the_form_field() }}
第一个jinja模板返回表单字段的标签。而第二个则返回表单字段本身。另外,表单字段和标签可以接受一个类的参数来进行样式设计。
我将添加所有的表单字段。
<form action="" method="post">
{{form.hidden_tag()}}
<div class="form-group m-5">
{{form.name.label()}}
{{form.name(class="form-control")}}
</div>
<div class="form-group m-5">
{{form.email.label()}}
{{form.email(class="form-control")}}
</div >
<div class="form-group m-5">
{{form.message.label()}}
{{form.message(class="form-control")}}
</div>
{{form.send(class="btn-lg btn-primary m-5")}}
</form>
你的联系表单应该与此类似,记住我们使用的是Bootstrap。你现在可以运行服务器并导航到联系页面来查看表单,以确保你做的是正确的事情。
处理表单数据
使用Flask-WTF扩展的表单处理过程很简单。在我们的联系路线中,当用户提交数据时,我们可以通过检查表单是否被验证,然后如果被验证,我们就可以获取数据了。
if form.validate_on_submit():
Var = form.form_variablename.data
当用户发送消息时,我们从联系表单中获取数据并在一个新的页面上呈现。你的联系路线逻辑应该有类似于此的东西。
@app.route("/contact", methods=["GET", "POST"])
def contact():
form = ContactForm()
if form.validate_on_submit():
name = form.name.data
email = form.email.data
message = form.message.data
return name + "<br /> " + email + "<br /> " + message
return render_template('contact.html', form=form)
Flask-WTForm扩展使评估表单数据变得更简单、更快速。它还可以确保对表单数据进行快速的验证检查,而不需要为每个验证检查编写每一个代码逻辑。
处理表单错误
当用户提交无效数据时,表单会遇到错误,我们可以捕获错误,但用户需要知道他/她做错了什么,以避免此类错误。Flask的Wtform使我们可以很容易地处理表单中的错误。
为了显示表单错误,我们导航到我们的联系表单模板。表单字段是我们要进行错误检查的地方。
第一步是检查表单字段本身是否有错误,然后传入表单字段的bootstrap类is-invalid。bootstrap类使得处理表单错误变得很容易,所以我在使用flask的wtf-forms时推荐使用它。
{% if form.email.errors %}
{{form.email(class="form-control is-invalid")}}
{% endif %}
下一步是循环浏览错误,并将它们显示在表单字段本身的下方。错误响应被包裹在一个带有bootstrap类的div中invalid-feedback 。
{% if form. email.errors %}
{{form.email(class="form-control is-invalid")}}
{% for error in form.email.errors %}
<div class="invalid-feedback">
<span>{{error}}</span>
</div>
{% endfor %}
{% endif %}
最后,写一个else语句来显示没有is-invalid bootstrap类的表单字段。
{% if form. email.errors %}
{{form.email(class="form-control is-invalid")}}
{% for error in form.email.errors %}
<div class="invalid-feedback">
<span>{{error}}</span>
</div>
{% endfor %}
{% else %}
{{form.email(class="form-control")}}
{% endif %}
在实现表单错误处理的最后,某个表单字段的整个块应该与下面的代码类似。
<div class="form-group m-5">
{{form.email.label()}}
{% if form. email.errors %}
{{form.email(class="form-control is-invalid")}}
{% for error in form.email.errors %}
<div class="invalid-feedback">
<span>{{error}}</span>
</div>
{% endfor %}
{% else %}
{{form.email(class="form-control")}}
{% endif %}
</div >
你可以对其他表单字段重复整个过程,这就是用flask-wtf扩展处理表单错误的简单程度。
总结
表单处理是Web应用程序的重要组成部分之一。本文说明了用Flask构建Web应用时处理表单的两种方法。
然而,Flask WTForms扩展是处理表单的最佳方法。它拥有处理表单所需的所有组件,这使得表单的编写变得简单。