一、Flask简介
Flask 是一个使用 Python 编写的微型 Web 框架。依赖 Jinja2 模板引擎和 Werkzeug WSGI 套件。这两个库的文档请移步:
- Jinja2 文档:Jinja是一个快速、富有表现力、可扩展的模板引擎。
- Werkzeug 文档:Werkzeug 是一个全面的 WSGI web 应用程序库。
默认情况下, Flask 不包含数据库抽象层、表单验证以及其他可以用已有库处理 的东西。Flask 通过大量的扩展(第三方包)支持各种各样的功能,以满足各种生产需要。
1.1 安装
Flask 支持 Python 3.6 以上版本。如果要支持 async
,因为会用到 contextvars.ContextVar
,所以需要 Python 3.7 以上版本。
1.2 依赖
当安装 Flask 时,以下依赖库会被自动安装:
- Werkzeug 用于实现 WSGI ,应用和服务之间的标准 Python 接口。
- Jinja2 用于渲染页面的模板语言。
- MarkupSafe 与 Jinja2 共用,在渲染页面时用于避免不可信的输入,防止注入攻击。
- ItsDangerous 保证数据完整性的安全标志数据,用于保护 Flask 的 session cookie.
- Click 是一个命令行应用的框架。用于提供
flask
命令,并允许添加自定义 管理命令。
1.3 可选依赖
以下库不会被自动安装。如果我们手动安装了,那么 Flask 会检测到这些库:
- Blinker 为信号提供支持。
- python-dotenv 当运行
flask
命令时为通过 dotenv 设置环境变量提供支持。 - Watchdog 为开发服务器提供快速高效的重载。
1.4 安装 Flask
使用 pip 安装:
pip install Flask
二、快速入门
2.1 最简单的 Flask 应用
创建一个hello.py文件(名称随意,但不要叫flask),写入以下内容:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
代码解析:
- 首先,我们导入了 Flask 类,该类的实例将会称为我们的 WSGI 应用。
- 然后,我们创建了 Flask 类的实例,参数是应用模块或者包的名称。通过该参数,Flask 才能知道在哪里可以找到模板和静态文件等东西。这里,我们使用了
__name__
,因为,我们的所有东西都在这一个文件中。 - 接着,我们使用
route()
装饰器来告诉 Flask 触该函数的 URL 。 - 最后,返回了需要在浏览器中展示的数据。默认的类型是 HTML,此字符串中的 HTML 会被浏览器渲染。
使用 flask 命令运行:
export FLASK_APP=hello
flask run
# Running on http://127.0.0.1:5000/
第一条命令设置了一个环境变量,以便 flask 找到我们的 flask 应用。但如果文件名为 app.py
或者 wsgi.py
,那么就不需要设置 FLASK_APP
环境变量。
运行第二条命令后打开http://127.0.0.1:5000/
,就可以看到“Hello World!”字样。
2.2 调试模式
flask run
命令默认以调试模式运行,在该模式下,服务器会在修改应用代码之后自动重启,并在页面上展示错误信息。不仅如此,在页面上,还提供了交互调试器,输入应用启动时终端中提供的Debugger PIN,就能在页面中进行调试。
如果需要打开所有开发功能,那么需要在运行 flask run
之前设置 FLASK_ENV
环境变量为 development
:
export FLASK_ENV=development
flask run
2.3 HTML 转义
当返回 HTML ( Flask 中的默认响应类型)时,为了防止注入攻击,所有用户提供的值在输出渲染前必须被转义。
手动转义方法:
from markupsafe import escape
@app.route("/<name>")
def hello(name):
return f"Hello, {
escape(name)}!"
路由中的 <name>
从 URL 中捕获值并将其传递给视图函数,假如用户提交的name
为<script>alert("bad")</script>
,那么这段代码会被转义为字符串直接输出,不会被渲染执行。
使用 Jinja2引擎(这个稍后会介绍)渲染的 HTML 模板会自动执行此操作。
2.4 路由
使用 route()
装饰器将视图函数绑定到 URL:
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
2.4.1 变量规则
通过把 URL 的一部分标记为 <变量名称>
就可以在 URL 中捕获变量。捕获的部分会作为关键字参数传递给函数。通过使用 <转换器:变量名>
,可以选择性的加上一个转换器,用以指定参数的类型。
转换器类型:
转换器 | 说明 |
---|---|
string |
(默认值) 接受任何不包含斜杠的文本 |
int |
接受正整数 |
float |
接受正浮点数 |
path |
类似string ,但可以包含斜杠 |
uuid |
接受 UUID 字符串 |
2.4.2 重定向行为
关于 URL 的制定规则,推荐在末尾带一个斜杠,如/index/
。如果用户在请求该 URL 时,写成了0/index
,那么 Flask 会自动进行重定向到/index/
。
如果开发者在制定 URL 时,没有带斜杠,如index
。那么,用户在访问index/
时,就会得到一个“404 not found”错误。这有助于保持这些资源的 url 唯一,还有助于搜索引擎避免对同一个页面进行两次索引。
2.4.3 URL 构建
url_for()
函数用于构建指定函数的 URL。第一个参数是函数名,它还可以接收任意个关键字参数,对应 URL 中的变量。其他参数会被当做 URL 的查询参数。
相对于硬编码到模板中的 URL,使用反向解析函数url_for()
来构建URL的好处如下:
- 反向解析比硬编码的 URL 更加直观;
- 方便集中管理 URL,只需要修改一次,而不是修改所有用到该 URL 的地方;
url_for()
会帮我们转义特殊字符;- 生成的路径总是绝对的,避免了浏览器中相对路径的意外行为;
- 如果你的应用被放置在 URL 根目录之外,例如,在
/myapplication
而不是/
,url_for()
会正确地为你处理它。
例如,这里我们使用 test_request_context()
方法来尝试使用 url_for()
。 test_request_context()
告诉 Flask 正在处理一个请求,但实际上我们只是在代码中测试,没有真正发出请求:
from flask import url_for
app = Flask(__name__)
@app.route