如何使用Flask和Python 3创建您的第一个网络应用程序

作者选择了自由与开源基金会作为写作捐赠计划的一部分接受捐赠。

引言

Flask是一个轻量级的Python网络框架,为使用Python语言创建网络应用提供了有用的工具和特性。它赋予开发者灵活性,并且对于新开发者来说是一个易于上手的框架,因为你可以仅用一个Python文件快速构建一个网络应用。Flask也是可扩展的,它不强制要求特定的目录结构,也不需要在开始前编写复杂的样板代码。

学习Flask将使你能够快速用Python创建网络应用。你可以利用Python库为你的网络应用添加高级功能,比如将数据存储在数据库中,或验证网络表单。

在本教程中,您将构建一个简单的Web应用程序,该应用程序在浏览器中渲染HTML文本。您将安装Flask,编写并运行一个Flask应用程序,并在开发模式下运行该应用程序。您将使用路由来展示服务于Web应用程序中不同目的的各种网页。您还将使用视图函数,允许用户通过动态路由与应用程序进行交互。最后,您将使用调试器来排查错误。

前提条件

步骤1 — 安装Flask

在这一步中,你将激活你的Python环境,并使用pip包安装程序来安装Flask。

首先,激活你的编程环境(如果你还没有这样做):

  1. source env/bin/activate

一旦你激活了编程环境,使用pip install命令来安装Flask:

  1. pip install flask

安装完成后,你会在输出的最后部分看到已安装的包列表,类似于以下内容:

Output
... Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, click, flask Successfully installed Jinja2-3.0.1 MarkupSafe-2.0.1 Werkzeug-2.0.1 click-8.0.1 flask-2.0.1 itsdangerous-2.0.1

这意味着安装Flask的同时也安装了其他几个包。这些包是Flask执行不同功能所需的依赖项。

你已经创建了项目文件夹、虚拟环境并安装了Flask。现在可以继续设置一个简单的应用程序了。

步骤2 — 创建一个简单的应用程序

现在你已经搭建好了编程环境,接下来将开始使用 Flask。在这一步中,你将在一个 Python 文件内创建一个小型的 Flask 网络应用,并在其中编写 HTML 代码以在浏览器中显示。

在你的 flask_app 目录下,打开名为 app.py 的文件进行编辑,可以使用 nano 或你喜欢的文本编辑器:

  1. nano app.py

app.py 文件中写入以下代码:

flask_app/app.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello():
    return '<h1>Hello, World!</h1>'

保存并关闭文件。

在上面的代码段中,你首先从 flask 包中导入了 Flask 对象。然后使用它来创建你的 Flask 应用实例,命名为 app。你传递了特殊的变量 __name__,它保存了当前 Python 模块的名称。这个名称告诉实例它的位置;Flask 需要这个信息来在后台设置一些路径。

一旦你创建了 app 实例,你就可以用它来处理传入的网络请求并向用户发送响应。@app.route 是一个装饰器,它将一个普通的 Python 函数转变为 Flask 视图函数,该视图函数将其返回值转换为 HTTP 响应,以便由 HTTP 客户端(如网络浏览器)显示。你向 @app.route() 传递值 '/',表示该函数将响应 URL / 的网络请求,这是主 URL。

hello()视图函数返回字符串'<h1>Hello, World!</h1>'作为HTTP响应。

你现在有一个简单的Flask应用程序,保存在名为app.py的Python文件中,下一步,你将运行该应用程序,以在网页浏览器中查看hello()视图函数的渲染结果。

步骤3 — 运行应用程序

创建包含Flask应用程序的文件后,你将使用Flask命令行接口启动开发服务器,并在浏览器中渲染你在上一步中作为hello()视图函数返回值编写的HTML代码。

首先,在激活虚拟环境的情况下,进入你的flask_app目录,使用FLASK_APP环境变量告诉Flask在哪里找到应用程序(在你的例子中是app.py),执行以下命令(在Windows上,使用set代替export):

  1. export FLASK_APP=app

然后,指定你希望在开发模式下运行应用程序(以便使用调试器捕捉错误),使用FLASK_ENV环境变量:

  1. export FLASK_ENV=development

最后,使用flask run命令运行应用程序:

  1. flask run

应用程序运行后,输出将类似于以下内容:

Output
* Serving Flask app "app" (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 296-353-699

上述输出包含几条信息,例如:

  • 你正在运行的应用程序的名称("app")。
  • 应用程序运行的环境(development)。
  • Debug mode: on表示Flask调试器正在运行。这在开发过程中非常有用,因为它在出现问题时提供详细的错误信息,使得故障排查更加容易。
  • 应用程序正在本地URL http://127.0.0.1:5000/ 上运行。127.0.0.1 是代表你机器的localhost的IP地址,而:5000是端口号。

打开浏览器并输入URL http://127.0.0.1:5000/。你将看到作为响应的<h1>标题中的文本Hello, World!。这确认了你的应用程序已成功运行。

如果你想停止开发服务器,按CTRL+C

警告:Flask 在开发环境中使用一个简单的 Web 服务器来运行你的应用程序,这也意味着 Flask 调试器正在运行,以便更容易捕获错误。你不应该在生产部署中使用此开发服务器。有关更多信息,请参阅 Flask 文档中的部署选项页面。你还可以查看这个使用 Gunicorn 部署 Flask 的教程使用 uWSGI 的教程,或者你可以按照如何在 App Platform 上使用 Gunicorn 部署 Flask 应用教程,使用 DigitalOcean App Platform 来部署你的 Flask 应用程序。

要继续开发 `app.py` 应用程序,请保持开发服务器运行并打开另一个终端窗口。进入 `flask_app` 目录,激活虚拟环境,设置环境变量 `FLASK_ENV` 和 `FLASK_APP`,然后继续执行下一步。(这些命令在本步骤前面已列出。)

注意: 当打开一个新的终端,或者在你关闭正在运行开发服务器的终端并希望重新运行它时,重要的是要记住激活虚拟环境并设置环境变量 FLASK_ENVFLASK_APP,以便 flask run 命令能够正常工作。

你只需要在一个终端窗口中运行一次服务器。

当一个 Flask 应用的开发服务器已经在运行时,使用相同的 flask run 命令来运行另一个 Flask 应用是不可能的。这是因为 flask run 默认使用端口号 5000,一旦被占用,该端口就无法用于运行另一个应用,你会收到类似以下的错误:

Output
OSError: [Errno 98] Address already in use

要解决这个问题,可以通过 CTRL+C 停止当前运行的服务器,然后再次运行 flask run,或者如果你想同时运行两个应用,可以为 -p 参数传递一个不同的端口号,例如,要在端口 5001 上运行另一个应用,使用以下命令:

  1. flask run -p 5001

这样,你可以在 http://127.0.0.1:5000/ 上运行一个应用,在 http://127.0.0.1:5001/ 上运行另一个应用,如果你愿意的话。

现在你拥有了一个小型的 Flask 网页应用。你已经运行了你的应用并在网页浏览器上显示了信息。接下来,你将学习有关路由的知识,以及如何使用它们来服务多个网页。

第四步 — 路由和视图函数

在这一步中,你将为应用添加几个路由,以便根据请求的URL显示不同的页面。你还将学习视图函数的概念以及如何使用它们。

一个路由是你可以用来确定用户在浏览器中访问你的Web应用时所获取内容的URL。例如,http://127.0.0.1:5000/可能是用于显示主页的主要路由。URL http://127.0.0.1:5000/about可能是用于关于页面的另一个路由,向访问者提供有关你的Web应用的一些信息。同样,你可以创建一个允许用户在http://127.0.0.1:5000/login登录你的应用的路由。

你当前的Flask应用只有一个路由,用于服务请求主URL (http://127.0.0.1:5000/) 的用户。为了演示如何向应用添加新的网页,你将编辑应用文件,添加另一个路由,该路由在http://127.0.0.1:5000/about提供有关你的Web应用的信息。

首先,打开你的app.py文件进行编辑:

  1. nano app.py

编辑文件,在文件末尾添加以下高亮代码:

flask_app/app.py
from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello():
    return '<h1>Hello, World!</h1>'


@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

保存并关闭文件。

你添加了一个名为 about() 的新函数。此函数通过 @app.route() 装饰器被转换为一个视图函数,负责处理对 http://127.0.0.1:5000/about 端点的请求。

在开发服务器运行的情况下,使用浏览器访问以下 URL:

http://127.0.0.1:5000/about

你将看到文本 This is a Flask web application.<h3> HTML 标题的形式呈现。

你还可以为一个视图函数设置多个路由。例如,你可以同时在 //index/ 提供首页。为此,打开你的 app.py 文件进行编辑:

  1. nano app.py

通过向 hello() 视图函数添加另一个装饰器来编辑文件:

flask_app/app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/index/')
def hello():
    return '<h1>Hello, World!</h1>'

@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

保存并关闭文件。

添加此新装饰器后,你可以在 http://127.0.0.1:5000/http://127.0.0.1:5000/index 两个地址访问首页。

现在你了解了什么是路由,如何使用它们创建视图函数,以及如何向应用程序添加新路由。接下来,你将使用动态路由,让用户能够控制应用程序的响应。

步骤 5 — 动态路由

在这一步中,您将使用动态路由来允许用户与应用程序进行交互。您将创建一个路由,用于将通过URL传递的单词大写,并创建另一个路由,用于将两个数字相加并显示结果。

通常情况下,用户不会通过手动编辑URL来与Web应用程序交互。相反,用户通过页面上的元素进行交互,这些元素会根据用户的输入和操作导向不同的URL。但为了本教程的目的,您将编辑URL以演示应用程序如何根据不同的URL做出不同的响应。

首先,打开您的app.py文件进行编辑:

  1. nano app.py

如果您允许用户向您的Web应用程序提交内容,比如您将在接下来的编辑中通过URL传递的值,您应该始终记住,应用程序不应直接显示不受信任的数据(用户提交的数据)。为了安全地显示用户数据,请使用markupsafe包附带的escape()函数,该包在安装Flask时一同被安装。

编辑app.py文件,并在文件顶部、Flask导入语句上方添加以下行:

flask_app/app.py
from markupsafe import escape
from flask import Flask

# ...

然后,在文件末尾添加以下路由:

flask_app/app.py
# ...

@app.route('/capitalize/<word>/')
def capitalize(word):
    return '<h1>{}</h1>'.format(escape(word.capitalize()))

保存并关闭文件。

这条新路由包含一个可变部分 `<word>`。它指示 Flask 从 URL 中提取值并传递给视图函数。URL 变量 `<word>` 将关键字参数传递给 `capitalize()` 视图函数。该参数与 URL 变量同名(本例中为 `word`)。通过这种方式,你可以访问通过 URL 传递的单词,并使用 Python 中的 `capitalize()` 方法响应其大写版本。

你使用之前导入的 `escape()` 函数将 `word` 字符串渲染为文本。这一点至关重要,以防止跨站脚本(XSS)攻击。如果用户提交的是恶意 JavaScript 而非单词,`escape()` 会将其渲染为文本,浏览器不会执行它,从而确保你的 Web 应用安全。

为了在 `<h1>` HTML 标题中显示大写的单词,你使用了 Python 的 `format()` 方法。更多关于此方法的信息,请参阅如何在 Python 3 中使用字符串格式化工具

在开发服务器运行的情况下,打开浏览器并访问以下 URL。你可以将高亮显示的单词替换为你选择的任意单词。

http://127.0.0.1:5000/capitalize/hello
http://127.0.0.1:5000/capitalize/flask
http://127.0.0.1:5000/capitalize/python

你将在页面上的 `<h1>` 标签中看到 URL 中的单词已大写。

您还可以在路由中使用多个变量。为了演示这一点,您将添加一个路由,该路由将两个正整数相加并显示结果。

打开您的app.py文件进行编辑:

  1. nano app.py

在文件末尾添加以下路由:

flask_app/app.py
# ...

@app.route('/add/<int:n1>/<int:n2>/')
def add(n1, n2):
    return '<h1>{}</h1>'.format(n1 + n2)

保存并关闭文件。

在这个路由中,您使用了一个特殊转换器int与URL变量(/add/<int:n1>/<int:n2>/),它仅接受正整数。默认情况下,URL变量被假定为字符串并按字符串处理。

在开发服务器运行的情况下,打开浏览器并访问以下URL:

http://127.0.0.1:5000/add/5/5/

结果将是这两个数字的和(在本例中为10)。

现在,您已经了解了如何使用动态路由根据请求的URL在单一路由中显示不同的响应。接下来,您将学习如何在出现错误时调试您的Flask应用程序。

步骤6 — 调试Flask应用程序

在开发Web应用程序时,您经常会遇到应用程序显示错误而不是您期望的行为的情况。您可能会拼错变量或忘记定义或导入函数。为了使解决这些问题变得更容易,Flask在开发模式下运行应用程序时提供了一个调试器。在这一步中,您将学习如何使用Flask调试器修复应用程序中的错误。

为了演示如何处理错误,您将创建一个路由,从用户名列表中向用户打招呼。

打开您的app.py文件进行编辑:

  1. nano app.py

在文件末尾添加以下路由:

flask_app/app.py
# ...

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    return '<h2>Hi {}</h2>'.format(users[user_id])

保存并关闭文件。

在上面的路由中,greet_user()视图函数从user_id URL变量接收一个user_id参数。您使用int转换器来接受正整数。在函数内部,您有一个名为users的Python列表,其中包含三个表示用户名的字符串。视图函数根据提供的user_id返回一个字符串。如果user_id0,响应将是Hi Bob,并用<h2>标签包裹,因为Bob是列表中的第一个项目(即users[0]的值)。

在开发服务器运行的情况下,打开浏览器并访问以下URL:

http://127.0.0.1:5000/users/0
http://127.0.0.1:5000/users/1
http://127.0.0.1:5000/users/2

您将收到以下响应:

Output
Hi Bob Hi Jane Hi Adam

到目前为止,这种方法运行良好,但当你请求一个不存在的用户的问候时,它可能会出错。为了演示Flask调试器的工作原理,请访问以下URL:

http://127.0.0.1:5000/users/3

你会看到一个类似这样的页面:

在页面顶部,你会看到Python异常的名称,即IndexError,这表明列表索引(在本例中为3)超出了列表的范围(因为列表只有三个元素,索引范围仅从02)。在调试器中,你可以看到追溯信息,它告诉你引发此异常的代码行。

追溯信息的最后两行通常指出了错误源头。在你的情况下,这些行可能类似于以下内容:

File "/home/USER/flask_app/app.py", line 28, in greet_user
    return '<h2>Hi {}</h2>'.format(users[user_id])

这表明错误源自app.py文件中的greet_user()函数,特别是在return语句处。

了解引发异常的原始行将有助于你确定代码中哪里出了问题,并决定如何修复它。

在这种情况下,你可以使用一个简单的try...except语句来修复这个错误。如果请求的URL索引超出了列表范围,用户将收到一个404 Not Found错误,这是一个HTTP错误,告诉用户他们所查找的页面不存在。

打开你的app.py文件进行编辑:

  1. nano app.py

要返回HTTP 404错误,你需要使用Flask的abort()函数,该函数可用于生成HTTP错误响应。修改文件中的第二行,同时导入此函数:

flask_app/app.py
from markupsafe import escape
from flask import Flask, abort

接着编辑greet_user()视图函数,使其如下所示:

flask_app/app.py
# ...

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    try:
        return '<h2>Hi {}</h2>'.format(users[user_id])
    except IndexError:
        abort(404)

你在上方使用try来测试return表达式是否存在错误。如果没有错误,即user_id的值与users列表中的某个索引相匹配,应用程序将返回相应的问候。如果user_id的值超出了列表范围,则会引发IndexError异常,你使用except捕获该错误,并通过Flask的abort()辅助函数响应HTTP 404错误。

现在,当开发服务器运行时,再次访问该URL:

http://127.0.0.1:5000/users/3

这次你会看到一个标准的404错误页面,告知用户该页面不存在。

本教程结束时,你的app.py文件将如下所示:

flask_app/app.py
from markupsafe import escape
from flask import Flask, abort

app = Flask(__name__)


@app.route('/')
@app.route('/index/')
def hello():
    return '<h1>Hello, World!</h1>'


@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

@app.route('/capitalize/<word>/')
def capitalize(word):
    return '<h1>{}</h1>'.format(escape(word.capitalize()))

@app.route('/add/<int:n1>/<int:n2>/')
def add(n1, n2):
    return '<h1>{}</h1>'.format(n1 + n2)

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    try:
        return '<h2>Hi {}</h2>'.format(users[user_id])
    except IndexError:
        abort(404)

至此,你已大致了解如何使用Flask调试器来排查错误,并帮助你确定解决这些错误的适当措施。

总结

你现在对 Flask 有了一个大致的了解,知道如何安装它,如何用它编写一个 Web 应用,如何运行开发服务器,以及如何使用路由和视图函数来展示服务于特定目的的不同网页。你也学会了如何使用动态路由让用户通过 URL 与你的 Web 应用进行互动,以及如何利用调试器来排查错误。

如果你想进一步了解 Flask,可以访问Flask 主题页面

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-your-first-web-application-using-flask-and-python-3