快速入门 — Flask 文档
快速入门
急于开始? 这个页面很好地介绍了 Flask。 它假设您已经安装了 Flask。 如果没有,请转到 安装 部分。
一个最小的应用程序
一个最小的 Flask 应用程序看起来像这样:
那么这段代码做了什么?
- 首先我们导入了
Flask
类。 此类的一个实例将是我们的 WSGI 应用程序。 - 接下来我们创建这个类的一个实例。 第一个参数是应用程序的模块或包的名称。 如果您使用的是单个模块(如本例中),则应使用
__name__
,因为根据它是作为应用程序启动还是作为模块导入,名称会有所不同('__main__'
与实际导入名称)。 这是必需的,以便 Flask 知道在哪里查找模板、静态文件等。 有关更多信息,请查看Flask
文档。 - 然后我们使用
route()
装饰器告诉 Flask 哪个 URL 应该触发我们的函数。 - 该函数被赋予一个名称,该名称也用于为该特定函数生成 URL,并返回我们希望在用户浏览器中显示的消息。
只需将其保存为 hello.py
或类似的内容。 确保不要调用您的应用程序 flask.py
,因为这会与 Flask 本身发生冲突。
要运行该应用程序,您可以使用 flask 命令或 python 的 -m
开关与 Flask。 在执行此操作之前,您需要通过导出 FLASK_APP
环境变量来告诉终端要使用的应用程序:
如果您使用的是 Windows,则环境变量语法取决于命令行解释器。 在命令提示符下:
在 PowerShell 上:
或者,您可以使用 python -m flask:
这将启动一个非常简单的内置服务器,它足以进行测试,但可能不是您想要在生产中使用的。 有关部署选项,请参阅 部署选项 。
现在转到 http://127.0.0.1:5000/,您应该会看到您的 hello world 问候语。
外部可见服务器
如果您运行服务器,您会注意到该服务器只能从您自己的计算机访问,而不能从网络中的任何其他计算机访问。 这是默认设置,因为在调试模式下,应用程序的用户可以在您的计算机上执行任意 Python 代码。
如果您禁用了调试器或信任您网络上的用户,您只需在命令行中添加 --host=0.0.0.0
即可使服务器公开可用:
这会告诉您的操作系统侦听所有公共 IP。
如果服务器没有启动怎么办
如果 python -m flask 失败或 flask 不存在,可能有多种原因。 首先,您需要查看错误消息。
旧版本的烧瓶
早于 0.11 的 Flask 版本曾经有不同的方式来启动应用程序。 简而言之,flask 命令不存在,python -m flask 也不存在。 在这种情况下,您有两个选择:要么升级到更新的 Flask 版本,要么查看 Development Server 文档以查看运行服务器的替代方法。
无效的导入名称
FLASK_APP
环境变量是要在 flask run 中导入的模块的名称。 如果模块命名不正确,您将在启动时收到导入错误(或者如果导航到应用程序时启用了调试)。 它会告诉您它尝试导入的内容以及失败的原因。
最常见的原因是打字错误或因为您实际上没有创建 app
对象。
调试模式
(只想记录错误和堆栈跟踪? 请参阅 应用程序错误 )
flask 脚本很适合启动本地开发服务器,但每次更改代码后都必须手动重新启动它。 这不是很好,Flask 可以做得更好。 如果您启用调试支持,服务器将在代码更改时重新加载自己,并且如果出现问题,它还将为您提供有用的调试器。
要启用所有开发功能(包括调试模式),您可以在运行服务器之前导出 FLASK_ENV
环境变量并将其设置为 development
:
(在 Windows 上,您需要使用 set
而不是 export
。)
这将执行以下操作:
- 它激活调试器
- 它激活自动重装器
- 它在 Flask 应用程序上启用调试模式。
您还可以通过导出 FLASK_DEBUG=1
来独立于环境控制调试模式。
Development Server 文档中解释了更多参数。
注意
即使交互式调试器在分叉环境中不起作用(这使得它几乎不可能在生产服务器上使用),它仍然允许执行任意代码。 这使它成为一个主要的安全风险,因此它 绝不能用于生产机器 。
运行中的调试器的屏幕截图:
class=screenshot align-center|screenshot of debugger in action 有关使用调试器的更多信息可以在 Werkzeug 文档 中找到。
有另一个调试器吗? 请参阅 使用调试器 。
路由
现代 Web 应用程序使用有意义的 URL 来帮助用户。 如果页面使用他们可以记住并用于直接访问页面的有意义的 URL,则用户更有可能喜欢该页面并返回。
使用 route()
装饰器将函数绑定到 URL。
你可以做得更多! 您可以使部分 URL 动态化并将多个规则附加到一个函数。
可变规则
您可以通过使用 <variable_name>
标记部分来向 URL 添加可变部分。 然后,您的函数接收 <variable_name>
作为关键字参数。 或者,您可以使用转换器来指定参数的类型,如 <converter:variable_name>
。
转换器类型:
string
|
(默认)接受任何不带斜杠的文本 |
int
|
接受正整数 |
float
|
接受正浮点值 |
path
|
像 string 但也接受斜线
|
uuid
|
接受 UUID 字符串 |
唯一 URL/重定向行为
以下两条规则在尾随斜杠的使用上有所不同。
projects
端点的规范 URL 有一个尾部斜杠。 它类似于文件系统中的文件夹。 如果您访问的 URL 没有尾部斜杠,Flask 会将您重定向到带有尾部斜杠的规范 URL。
about
端点的规范 URL 没有尾部斜杠。 它类似于文件的路径名。 访问带有斜杠的 URL 会产生 404“未找到”错误。 这有助于保持这些资源的 URL 唯一,这有助于搜索引擎避免将同一页面索引两次。
网址构建
要构建特定函数的 URL,请使用 url_for()
函数。 它接受函数名作为它的第一个参数和任意数量的关键字参数,每个参数对应于 URL 规则的一个可变部分。 未知变量部分作为查询参数附加到 URL。
为什么要使用 URL 反向函数 url_for()
来构建 URL,而不是将它们硬编码到模板中?
- 反转通常比硬编码 URL 更具描述性。
- 您可以一次性更改您的 URL,而无需记住手动更改硬编码的 URL。
- URL 构建透明地处理特殊字符和 Unicode 数据的转义。
- 生成的路径总是绝对的,避免了浏览器中相对路径的意外行为。
- 如果您的应用程序位于 URL 根之外,例如,在
/myapplication
而不是/
,url_for()
会为您正确处理。
比如这里我们用test_request_context()
的方法来试一下url_for()
。 test_request_context()
告诉 Flask 即使在我们使用 Python shell 时也要表现得好像它在处理请求。 参见 上下文局部变量 。
HTTP 方法
Web 应用程序在访问 URL 时使用不同的 HTTP 方法。 在使用 Flask 时,您应该熟悉 HTTP 方法。 默认情况下,路由只响应 GET
请求。 您可以使用 route()
装饰器的 methods
参数来处理不同的 HTTP 方法。
如果存在 GET
,Flask 会自动添加对 HEAD
方法的支持,并根据 HTTP RFC 处理 HEAD
请求。 同样,OPTIONS
会自动为您实现。
静态文件
动态 Web 应用程序也需要静态文件。 这通常是 CSS 和 JavaScript 文件的来源。 理想情况下,您的 Web 服务器被配置为为您服务,但在开发过程中 Flask 也可以这样做。 只需在您的包中或模块旁边创建一个名为 static
的文件夹,它将在应用程序的 /static
处可用。
要为静态文件生成 URL,请使用特殊的 'static'
端点名称:
该文件必须以 static/style.css
的形式存储在文件系统上。
渲染模板
在 Python 中生成 HTML 并不有趣,而且实际上相当麻烦,因为您必须自己进行 HTML 转义以确保应用程序安全。 因此,Flask 会自动为您配置 Jinja2 模板引擎。
要渲染模板,您可以使用 render_template()
方法。 您所要做的就是提供模板的名称和要作为关键字参数传递给模板引擎的变量。 这是一个如何呈现模板的简单示例:
Flask 将在 templates
文件夹中寻找模板。 所以如果你的应用程序是一个模块,这个文件夹就在那个模块旁边,如果它是一个包,它实际上在你的包中:
案例1:一个模块:
案例2:一个包裹:
对于模板,您可以使用 Jinja2 模板的全部功能。 前往官方 Jinja2 模板文档 了解更多信息。
这是一个示例模板:
在模板中,您还可以访问 request、session 和 g 1 对象以及 get_flashed_messages()
函数.
如果使用继承,模板特别有用。 如果您想知道它是如何工作的,请转到 模板继承 模式文档。 基本上模板继承可以在每个页面上保留某些元素(如页眉、导航和页脚)。
自动转义已启用,因此如果 name
包含 HTML,它将自动转义。 如果您可以信任一个变量并且您知道它将是安全的 HTML(例如因为它来自将 wiki 标记转换为 HTML 的模块),您可以通过使用 Markup
类或使用模板中的 |safe
过滤器。 前往 Jinja 2 文档了解更多示例。
下面是对 Markup
类的工作原理的基本介绍:
0.5 版更改: 不再为所有模板启用自动转义。 以下模板扩展会触发自动转义:.html
、.htm
、.xml
、.xhtml
。 从字符串加载的模板将禁用自动转义。
- 1
- 不确定 g 对象是什么? 您可以在其中存储自己需要的信息,请查看该对象的文档 (g) 和 Using SQLite 3 with Flask 以获取更多信息。
访问请求数据
对于 Web 应用程序,对客户端发送到服务器的数据做出反应至关重要。 在 Flask 中,此信息由全局 request 对象提供。 如果您对 Python 有一些经验,您可能想知道该对象如何成为全局对象以及 Flask 如何设法仍然是线程安全的。 答案是上下文本地人:
上下文局部变量
内幕消息
如果您想了解它是如何工作的以及如何使用上下文本地变量实现测试,请阅读本节,否则请跳过它。
Flask 中的某些对象是全局对象,但不是通常的类型。 这些对象实际上是特定上下文本地对象的代理。 多嘴。 但这实际上很容易理解。
想象上下文是处理线程。 一个请求进来,Web 服务器决定生成一个新线程(或其他东西,底层对象能够处理线程以外的并发系统)。 当 Flask 开始其内部请求处理时,它会确定当前线程是活动上下文,并将当前应用程序和 WSGI 环境绑定到该上下文(线程)。 它以一种智能的方式做到这一点,以便一个应用程序可以在不中断的情况下调用另一个应用程序。
那么这对你意味着什么? 基本上你可以完全忽略这种情况,除非你在做单元测试之类的事情。 您会注意到依赖于请求对象的代码会突然中断,因为没有请求对象。 解决方案是自己创建一个请求对象并将其绑定到上下文。 单元测试最简单的解决方案是使用 test_request_context()
上下文管理器。 结合 with
语句,它将绑定一个测试请求,以便您可以与之交互。 下面是一个例子:
另一种可能性是将整个 WSGI 环境传递给 request_context()
方法:
请求对象
请求对象记录在 API 部分,我们不会在这里详细介绍(参见 Request
)。 以下是一些最常见操作的广泛概述。 首先,您必须从 flask
模块导入它:
当前请求方法可通过使用 method
属性获得。 要访问表单数据(在 POST
或 PUT
请求中传输的数据),您可以使用 form
属性。 以下是上述两个属性的完整示例:
如果 form
属性中不存在密钥会怎样? 在这种情况下,会引发一个特殊的 KeyError
。 您可以像标准 KeyError
一样捕获它,但如果不这样做,则会显示 HTTP 400 错误请求错误页面。 因此,在许多情况下,您不必处理该问题。
要访问在 URL (?key=value
) 中提交的参数,您可以使用 args
属性:
我们建议使用 get 或通过捕获 KeyError
来访问 URL 参数,因为用户可能会更改 URL 并向他们呈现 400 错误的请求页面,在这种情况下对用户不友好。
有关请求对象的方法和属性的完整列表,请转到 Request
文档。
文件上传
您可以轻松地使用 Flask 处理上传的文件。 只要确保不要忘记在 HTML 表单上设置 enctype="multipart/form-data"
属性,否则浏览器根本不会传输您的文件。
上传的文件存储在内存中或文件系统上的临时位置。 您可以通过查看请求对象上的 files
属性来访问这些文件。 每个上传的文件都存储在该字典中。 它的行为就像一个标准的 Python file
对象,但它还有一个 save()
方法,允许您将该文件存储在服务器的文件系统上。 这是一个简单的例子,展示了它是如何工作的:
如果您想知道文件在上传到您的应用程序之前在客户端上是如何命名的,您可以访问 filename
属性。 但是请记住,这个值是可以伪造的,所以永远不要相信那个值。 如果要使用客户端的文件名将文件存储在服务器上,请通过 Werkzeug 为您提供的 secure_filename()
函数传递:
有关更好的示例,请查看 上传文件 模式。
重定向和错误
要将用户重定向到另一个端点,请使用 redirect()
函数; 要提前中止带有错误代码的请求,请使用 abort()
函数:
这是一个相当无意义的例子,因为用户将从索引重定向到他们无法访问的页面(401 表示访问被拒绝),但它显示了它是如何工作的。
默认情况下,每个错误代码都会显示一个黑白错误页面。 如果要自定义错误页面,可以使用 errorhandler()
装饰器:
注意 render_template()
调用后的 404
。 这告诉 Flask 该页面的状态代码应该是 404,这意味着未找到。 默认情况下假定 200 转换为:一切顺利。
有关更多详细信息,请参阅 错误处理程序 。
关于回复
视图函数的返回值会自动转换为您的响应对象。 如果返回值是一个字符串,它被转换为一个响应对象,该字符串作为响应主体、一个 200 OK
状态代码和一个 text/html mimetype。 如果返回值是 dict,则调用 jsonify()
以产生响应。 Flask 将返回值转化为响应对象的逻辑如下:
- 如果返回正确类型的响应对象,它将直接从视图返回。
- 如果它是一个字符串,则使用该数据和默认参数创建一个响应对象。
- 如果是 dict,则使用
jsonify
创建响应对象。 - 如果返回元组,元组中的项目可以提供额外信息。 此类元组必须采用
(response, status)
、(response, headers)
或(response, status, headers)
的形式。status
值将覆盖状态代码,headers
可以是附加标题值的列表或字典。 - 如果这些都不起作用,Flask 将假定返回值是一个有效的 WSGI 应用程序并将其转换为响应对象。
如果您想在视图中获取结果响应对象,您可以使用 make_response()
函数。
想象一下你有一个这样的视图:
你只需要用 make_response()
包裹返回表达式并获取响应对象来修改它,然后返回它:
带有 JSON 的 API
编写 API 时常见的响应格式是 JSON。 开始使用 Flask 编写这样的 API 很容易。 如果您从视图返回 dict
,它将被转换为 JSON 响应。
根据您的 API 设计,您可能希望为 dict
以外的类型创建 JSON 响应。 在这种情况下,请使用 jsonify()
函数,该函数将序列化任何支持的 JSON 数据类型。 或者查看支持更复杂应用程序的 Flask 社区扩展。
会话
除了请求对象之外,还有一个名为 session 的对象,它允许您从一个请求到下一个请求存储特定于用户的信息。 这是在 cookie 之上为您实现的,并以加密方式对 cookie 进行签名。 这意味着用户可以查看您的 cookie 的内容但不能修改它,除非他们知道用于签名的密钥。
为了使用会话,您必须设置一个密钥。 以下是会话的工作原理:
如果您不使用模板引擎(如本例所示),此处提到的 escape()
确实会为您转义。
关于基于 cookie 的会话的注意事项:Flask 将获取您放入会话对象中的值并将它们序列化为 cookie。 如果您发现某些值在请求中没有持续存在,确实启用了 cookie,并且您没有收到明确的错误消息,请检查页面响应中 cookie 的大小与 Web 浏览器支持的大小相比。
除了默认的基于客户端的会话,如果你想在服务器端处理会话,有几个 Flask 扩展支持这个。
消息闪烁
好的应用程序和用户界面都是关于反馈的。 如果用户没有得到足够的反馈,他们可能最终会讨厌该应用程序。 Flask 提供了一种非常简单的方法来向具有闪烁系统的用户提供反馈。 闪烁系统基本上可以在请求结束时记录消息并在下一个(并且仅下一个)请求时访问它。 这通常与布局模板结合以公开消息。
要闪现消息,请使用 flash()
方法,要获取消息,您可以使用 get_flashed_messages()
,它也可在模板中使用。 查看 消息闪烁 以获取完整示例。
日志记录
0.3 版中的新功能。
有时您可能会遇到这样的情况:您处理的数据应该是正确的,但实际上却不是。 例如,您可能有一些客户端代码向服务器发送 HTTP 请求,但显然格式不正确。 这可能是由用户篡改数据或客户端代码失败引起的。 大多数情况下,在这种情况下用 400 Bad Request
回复是可以的,但有时这行不通,代码必须继续工作。
您可能仍然想记录一些可疑的事情发生。 这是记录器派上用场的地方。 从 Flask 0.3 开始,已经预先配置了一个记录器供您使用。
以下是一些示例日志调用:
随附的 logger
是标准日志记录 Logger
,因此请前往官方 logging
文档了解更多信息。
阅读有关 应用程序错误 的更多信息。
在 WSGI 中间件中挂钩
要将 WSGI 中间件添加到 Flask 应用程序,请包装应用程序的 wsgi_app
属性。 例如,应用 Werkzeug 的 ProxyFix
中间件在 Nginx 后面运行:
包裹 app.wsgi_app
而不是 app
意味着 app
仍然指向你的 Flask 应用程序,而不是中间件,所以你可以直接继续使用和配置 app
.
使用 Flask 扩展
扩展是帮助您完成常见任务的包。 例如,Flask-SQLAlchemy 提供了 SQLAlchemy 支持,使其与 Flask 一起使用变得简单易用。
有关 Flask 扩展的更多信息,请查看 扩展 。