作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。
介绍
网页表单,如文本字段和文本区域,让用户能够将数据发送到应用程序,无论是下载或无线电按钮,该应用程序将使用执行一个操作,或发送大量的文本区域进行处理或显示,例如,在社交媒体应用程序中,您可能给用户一个框,他们可以将新内容添加到他们的页面。
Flask是一个轻量级的Python网页框架,提供用于在Python语言中创建网页应用程序的有用的工具和功能。为了在Flask中以安全和灵活的方式渲染和验证网页表单,您将使用Flask-WTF(https://flask-wtf.readthedocs.io/en/1.0.x/),这是一个Flask扩展,可帮助您在Flask应用程序中使用WTForms库。
WTForms是一个 Python 库,提供灵活的 Web 表单渲染。 您可以使用它来渲染文本字段、文本区域、密码字段、无线电按钮等。 WTForms 还提供使用不同的 validators 进行强大的数据验证,以验证用户提交的数据符合您定义的某些标准。 例如,如果您有所需的字段,您可以确保用户提交的数据提供,或具有一定的长度。
WTForms 还使用 CSRF 代币来提供保护,以防止 CSRF 攻击,这些攻击允许攻击者在用户身份验证的 Web 应用程序上执行不必要的操作。成功的 CSRF 攻击可以迫使用户执行状态改变的请求,例如将资金转移到攻击者的银行账户中,在银行应用程序中更改用户的电子邮件地址等。
在本教程中,您将构建一个小型的Web应用程序,该应用程序将有一个页面,用于显示存储在Python列表中的课程,而索引页面将有一个形式,用于输入课程标题,其描述,价格,可用性和水平(初学者,中级或高级)。
前提条件
*本地 Python 3 编程环境. 在 [如何安装和设置Python 3的本地编程环境]系列(https://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming-environment-for-python-3)中跟随操作系统的教程. 在本教程中,您将调用项目目录 flask_app
- 了解基本的 Flask 概念,如路线、视图功能和模板。如果您不熟悉 Flask,请参阅 如何使用 Flask 和 Python 创建您的第一个 Web 应用程序和 如何在 Flask 应用程序中使用模板。
- 了解基本的 HTML 概念。您可以查看我们的 如何使用 HTML 网站教程系列以获得背景知识.(_
步骤 1 — 安装 Flask 和 Flask-WTF
在此步骤中,您将安装 Flask 和 Flask-WTF,这也将自动安装 WTForms 库。
随着虚拟环境的启用,使用管道来安装Flask和Flask-WTF:
1pip install Flask Flask-WTF
一旦安装成功完成,您将在输出结束时看到一个类似于以下的行:
1[secondary_label Output]
2Successfully installed Flask-2.0.2 Flask-WTF-1.0.0 Jinja2-3.0.3 MarkupSafe-2.0.1 WTForms-3.0.0 Werkzeug-2.0.2 click-8.0.3 itsdangerous-2.0.1
正如你所看到的,WTForms库也被安装为Flask-WTF包的依赖性。
现在你已经安装了所需的Python包,你将下一步设置一个Web表单。
步骤2 - 设置表格
在此步骤中,您将使用从 WTForms 库导入的字段和验证器设置 Web 表单。
您将设置以下领域:
- **标题:**课程标题的文本输入字段
- **描述:**课程描述的文本区域字段
- **价格:**课程价格的整数字段
- **水平:**课程级别的无线电字段有三种选择:初学者,中学者和高级
- **可用:**一个检查框字段,表示课程是否目前可用
首先,在您的flask_app目录中打开一个名为forms.py的新文件,该文件将包含您在应用程序中需要的表单:
1nano forms.py
此文件将有一个代表您的 Web 表格的类别. 添加以下导入在顶部:
1[label flask_app/forms.py]
2from flask_wtf import FlaskForm
3from wtforms import (StringField, TextAreaField, IntegerField, BooleanField,
4 RadioField)
5from wtforms.validators import InputRequired, Length
要构建网页表格,您将创建一个FlaskForm基础类的子类,您将其从flask_wtf包中导入。
您从 WTForms 库中导入以下 字段:
StringField:文本输入TextAreaField:文本区域字段IntegerField:整数字段BooleanField:检查框字段RadioField:用于显示用户可选择的无线电按钮列表的字段
在从 wtforms.validators 导入InputRequired,长度行中,您将导入验证器用于字段,以确保用户提交有效数据。
接下来,在进口语句后添加下面的 类:
1[label flask_app/forms.py]
2
3class CourseForm(FlaskForm):
4 title = StringField('Title', validators=[InputRequired(),
5 Length(min=10, max=100)])
6 description = TextAreaField('Course Description',
7 validators=[InputRequired(),
8 Length(max=200)])
9 price = IntegerField('Price', validators=[InputRequired()])
10 level = RadioField('Level',
11 choices=['Beginner', 'Intermediate', 'Advanced'],
12 validators=[InputRequired()])
13 available = BooleanField('Available', default='checked')
保存并关闭文件。
在此CourseForm类中,您将继承从您之前导入的FlaskForm基础类。 您将表单字段的集合定义为类变量,使用您从 WTForms 库导入的表单字段。
您可以通过从wtforms.validators模块中导入的验证器列表来定义每个字段的验证器。
InputRequired: 表示该字段不应该是空的长度: 需要两个参数;min设置为10' 以确保标题长度至少为 10 个字符,而max设置为100' 以确保标题长度不超过 100 个字符。
描述文本区域域有一个InputRequired验证器和一个Length验证器,其max参数设置为200,没有min参数的值,这意味着唯一的要求是它不超过200个字符。
类似地,您定义了名为价格的课程价格所需的整数字段。
水平字段是一个具有多个选择的无线电字段,您在Python列表中定义选项并将其传输到选择参数中,您还使用InputRequired验证器根据需要定义该字段。
该可用字段是一个检查框的字段. 您通过将其转移到默认参数来设置默认的已检查值。
有关如何使用 WTForms 库的更多信息,请参阅 WTForms 文档上的 Crash Course 页面。
您已经在forms.py文件中配置了网页表格,接下来,您将创建一个Flask应用程序,导入该表格,并在索引页面上显示其字段。
步骤 3 – 显示 Web 表格和课程
在此步骤中,您将创建一个Flask应用程序,在索引页面上显示您在上一步创建的Web表单,并创建课程列表和页面以显示课程。
当您的编程环境启用并安装Flask时,请打开名为app.py的文件,在您的flask_app目录中进行编辑:
1nano app.py
此文件将从 Flask 导入所需的类和助手,并从 forms.py 文件中导入 CourseForm. 您将构建课程列表,然后实例表格并将其传输到模板文件中。
1[label flask_app/app.py]
2from flask import Flask, render_template, redirect, url_for
3from forms import CourseForm
4
5app = Flask(__name__)
6app.config['SECRET_KEY'] = 'your secret key'
7
8courses_list = [{
9 'title': 'Python 101',
10 'description': 'Learn Python basics',
11 'price': 34,
12 'available': True,
13 'level': 'Beginner'
14 }]
15
16@app.route('/', methods=('GET', 'POST'))
17def index():
18 form = CourseForm()
19 return render_template('index.html', form=form)
保存并关闭文件。
以下是从 Flask 导入的内容:
- 创建 Flask 应用程序实例的
Flask类 - 返回索引模板的
render_template()函数 - 重定向() 函数 在添加新课程后将用户重定向到课程页面
- 构建 URL 的
url_for()函数
首先从forms.py文件中导入CourseForm()类,然后创建一个名为app的Flask应用程序实例。
您已为 WTForms 设置一个 secret key 配置,用于生成 CSRF 代币来保护您的 Web 表单. 秘密密密钥应该是一个长的随机字符串. 请参阅 如何在 Flask 应用程序中使用 Web 表单的步骤 3 有关如何获取秘密密密钥的更多信息。
然后你创建一个名为courses_list的字典列表,该词典目前有一个名为Python 101的示例课程。在这里,你将使用Python列表作为演示目的的数据存储库。在现实世界的情况下,你将使用SQLite等数据库。 参阅如何在Flask应用程序中使用SQLite数据库(https://andsky.com/tech/tutorials/how-to-use-an-sqlite-database-in-a-flask-application),了解如何使用数据库来存储你的课程数据。
您使用app.route()装饰器在index()视图函数中创建一个/主路线,它在methods参数中接受GET和POST HTTP 方法。
您实例化代表 Web 表单的 CourseForm() 类,并将该实例保存到名为 form 的变量中,然后返回对 render_template() 函数的呼叫,并将其传递给名为 index.html 的模板文件和表单实例。
要在索引页面上显示网页表格,您首先将创建一个基础模板,该模板将包含其他模板也将使用的所有基本HTML代码,以避免代码重复。
在您的flask_app目录中创建一个模板文件夹,Flask 搜索模板,然后打开名为base.html的模板文件,它将是其他模板的基板模板:
1mkdir templates
2nano templates/base.html
将下列代码添加到 base.html 文件中,以创建一个 navbar 和一个内容块的 base 模板:
1[label flask_app/templates/base.html]
2<!DOCTYPE html>
3<html lang="en">
4<head>
5 <meta charset="UTF-8">
6 <title>{% block title %} {% endblock %} - FlaskApp</title>
7 <style>
8 nav a {
9 color: #d64161;
10 font-size: 3em;
11 margin-left: 50px;
12 text-decoration: none;
13 }
14 </style>
15</head>
16<body>
17 <nav>
18 <a href="{{ url_for('index') }}">FlaskApp</a>
19 <a href="#">About</a>
20 </nav>
21 <hr>
22 <div class="content">
23 {% block content %} {% endblock %}
24 </div>
25</body>
26</html>
此基础模板包含您在其他模板中需要重复使用的所有HTML锅炉板。标题块将被更换为为每个页面设置一个标题,而内容块将被替换为每个页面的内容。导航栏有两个链接,一个用于索引页面,其中您使用url_for()辅助函数链接到index()视图函数,另一个用于关于页面,如果您选择在应用程序中包含一个链接。
保存并关闭文件。
接下来,打开一个名为index.html的模板,这是你在app.py文件中提到的模板:
1nano templates/index.html
此文件将包含您通过form变量传递到index.html模板的网页表格,添加以下代码:
1[label flask_app/templates/index.html]
2{% extends 'base.html' %}
3
4{% block content %}
5 <h1>{% block title %} Add a New Course {% endblock %}</h1>
6
7 <form method="POST" action="/">
8 {{ form.csrf_token }}
9 <p>
10 {{ form.title.label }}
11 {{ form.title(size=20) }}
12 </p>
13
14 {% if form.title.errors %}
15 <ul class="errors">
16 {% for error in form.title.errors %}
17 <li>{{ error }}</li>
18 {% endfor %}
19 </ul>
20 {% endif %}
21
22 <p>
23 {{ form.description.label }}
24 </p>
25 {{ form.description(rows=10, cols=50) }}
26
27 {% if form.description.errors %}
28 <ul class="errors">
29 {% for error in form.description.errors %}
30 <li>{{ error }}</li>
31 {% endfor %}
32 </ul>
33 {% endif %}
34
35 <p>
36 {{ form.price.label }}
37 {{ form.price() }}
38 </p>
39
40 {% if form.price.errors %}
41 <ul class="errors">
42 {% for error in form.price.errors %}
43 <li>{{ error }}</li>
44 {% endfor %}
45 </ul>
46 {% endif %}
47
48 <p>
49 {{ form.available() }} {{ form.available.label }}
50 </p>
51
52 {% if form.available.errors %}
53 <ul class="errors">
54 {% for error in form.available.errors %}
55 <li>{{ error }}</li>
56 {% endfor %}
57 </ul>
58 {% endif %}
59
60 <p>
61 {{ form.level.label }}
62 {{ form.level() }}
63 </p>
64
65 {% if form.level.errors %}
66 <ul class="errors">
67 {% for error in form.level.errors %}
68 <li>{{ error }}</li>
69 {% endfor %}
70 </ul>
71 {% endif %}
72
73 <p>
74 <input type="submit" value="Add">
75 </p>
76 </form>
77
78{% endblock %}
保存并关闭文件。
您将基础模板扩展,并在一个<h1>标签中设置一个标题,然后您将网页表单字段转换为<form>标签,将其方法设置为POST,并将操作转移到/主路线,即索引页面。
您可以使用form.field.label语法渲染每个字段,并使用form.field.label语法渲染其标签。您可以将参数传输到该字段以控制其显示方式。例如,您将标题输入字段的大小设置为{{form.title(size=20) }},并通过参数行和cols来设置描述文本区域的行和列的数量,就像您通常在HTML中所做的那样。
您可以使用语法if form.field.errors检查验证错误,如果一个字段有错误,则使用for循环循环循环通过它们,并在字段下面列出它们。
在您的flask_app目录中启用虚拟环境时,请使用FLASK_APP环境变量告诉Flask关于该应用程序(app.py在这种情况下)。然后将FLASK_ENV环境变量设置为development,以便在开发模式下运行应用程序,并获取调试器的访问。有关Flask调试器的更多信息,请参阅如何处理Flask应用程序中的错误(LINK0))。
1export FLASK_APP=app
2export FLASK_ENV=development
接下来,运行应用程序:
1flask run
当开发服务器运行时,请使用您的浏览器访问以下URL:
1http://127.0.0.1:5000/
您将看到在索引页面上显示的 Web 表格:

尝试提交表单而不填写标题. 你会看到一个错误消息,通知你标题是必需的. 通过提交错误的数据(如短标题小于10个字符长度,或描述超过200个字符长度)来查看其他错误消息来尝试表单。
用有效的数据填写表单到目前为止没有任何效果,因为您没有处理表单提交的代码。
现在,您需要一个页面来显示您在列表中的课程. 后来,处理网页表格数据将添加一个新课程到列表,并将用户重定向到课程页面,以查看新课程添加到它。
让开发服务器运行,然后打开另一个终端窗口。
接下来,打开app.py来添加课程路线:
1nano app.py
添加下列路径到文件的末尾:
1[label flask_app/app.py]
2# ...
3
4@app.route('/courses/')
5def courses():
6 return render_template('courses.html', courses_list=courses_list)
保存并关闭文件。
此路径将显示一个名为courses.html的模板,并将其传输到courses_list列表中。
然后创建courses.html模板以显示课程:
1nano templates/courses.html
添加以下代码:
1[label flask_app/templates/courses.html]
2{% extends 'base.html' %}
3
4{% block content %}
5 <h1>{% block title %} Courses {% endblock %}</h1>
6 <hr>
7 {% for course in courses_list %}
8 <h2> {{ course['title'] }} </h2>
9 <h4> {{ course['description'] }} </h4>
10 <p> {{ course['price'] }}$ </p>
11 <p><i>({{ course['level'] }})</i></p>
12 <p>Availability:
13 {% if course['available'] %}
14 Available
15 {% else %}
16 Not Available
17 {% endif %}</p>
18 <hr>
19 {% endfor %}
20{% endblock %}
保存并关闭文件。
您通过courses_list列表中的项目设置一个标题和循环。您将标题显示在<h2>标签中,描述显示在<h4>标签中,价格和课程水平显示在<p>标签中。
使用您的浏览器前往课程页面:
1http://127.0.0.1:5000/courses/
你会看到一页显示一个课程,因为到目前为止,你的课程列表中只有一门课程:

接下来,打开base.html,在导航栏中添加链接到课程页面:
1nano templates/base.html
编辑它看起来如下:
1[label flask_app/templates/base.html]
2<!DOCTYPE html>
3<html lang="en">
4<head>
5 <meta charset="UTF-8">
6 <title>{% block title %} {% endblock %} - FlaskApp</title>
7 <style>
8 nav a {
9 color: #d64161;
10 font-size: 3em;
11 margin-left: 50px;
12 text-decoration: none;
13 }
14 </style>
15</head>
16<body>
17 <nav>
18 <a href="{{ url_for('index') }}">FlaskApp</a>
19 <a href="{{ url_for('courses') }}">Courses</a>
20 <a href="#">About</a>
21 </nav>
22 <hr>
23 <div class="content">
24 {% block content %} {% endblock %}
25 </div>
26</body>
27</html>
保存并关闭文件。
更新索引页面,您将在导航栏中看到一个新的 课程链接。
您已经创建了应用程序所需的页面:一个索引页面,包含添加新课程的网页表,以及显示您列出的课程的页面。
要使应用程序功能,您需要通过验证它并将其添加到课程列表来处理用户提交的Web表单数据。
步骤 4 – 访问表单数据
在此步骤中,您将访问用户提交的数据,验证并将其添加到课程列表中。
打开app.py以添加用于在index()函数内处理 Web 表单数据的代码:
1nano app.py
编辑index()函数以显示如下:
1[label flask_app/app.py]
2# ...
3@app.route('/', methods=('GET', 'POST'))
4def index():
5 form = CourseForm()
6 if form.validate_on_submit():
7 courses_list.append({'title': form.title.data,
8 'description': form.description.data,
9 'price': form.price.data,
10 'available': form.available.data,
11 'level': form.level.data
12 })
13 return redirect(url_for('courses'))
14 return render_template('index.html', form=form)
保存和关闭文件
在这里,您在表单对象上呼叫validate_on_submit()方法,该方法会检查请求是否是一个 POST 请求,并运行您为每个字段配置的验证器。
如果提交的表单数据是有效的,则条件为真,并且将执行如果声明下的代码。您构建一个课程字典,并使用附加方法将新课程添加到courses_list列表中。
随着开发服务器运行,请访问索引页面:
1http://127.0.0.1:5000/
用有效的数据填写表格并提交它,您将被重定向到课程页面,您将看到新课程显示在其上。
结论
您创建了一个 Flask 应用程序,该应用程序具有使用 Flask-WTF 扩展和 WTForms 库构建的 Web 表单,该表单有几种类型的字段来接收用户的数据,使用特殊的 WTForms 验证器验证它,并将其添加到数据存储中。
如果您想了解更多关于 Flask 的信息,请参阅 如何使用 Flask 创建网站系列的其他教程。