一、请求生命周期
Flask 请求的生命周期涉及到整个处理请求的过程,包括请求的接收、视图函数的执行、响应的生成和发送等。以下是一个简要的 Flask 请求生命周期的概述:
-
WSGI 服务器调用 Flask 对象,该对象调用 Flask.wsgi_app() 。
-
一个 RequestContext 对象被创建,将 WSGI environ 字典转换为一个 Request 对象。它还创建一个 AppContext 对象。
-
app context 被推送,这使得 current_app 和 g 可用。
-
发送 appcontext_pushed 信号。
-
request context 被推送,这使得 request 和 session 可用。
-
会话被打开,使用应用程序的 session_interface ,一 个 SessionInterface 实例,载入所有现存的会话数据。
-
将 URL 与在应用设置期间使用 route() 装饰器注册的 URL 规则进行匹配。如果没有匹配项,则错误(通常是 404 、405 或重 定向)被存储以供以后处理。
-
发送 request_started 信号。
-
调用所有 url_value_preprocessor() 装饰的函数。
-
调用所有 before_request() 装饰的函数。如果有任何返回值,那么就立即被视为响应。
-
如果 URL 在几个步骤前与路由不匹配,则现在会引发该错误。
-
与匹配的 URL 关联的 route() 装饰器视图函数 被调用并返回要用作响应的值。
-
如果到目前为止的任何步骤引发了异常,并且有一个 errorhandler() 装饰器函数与异常类或 HTTP 错误代码匹 配,那么调用它处理错误并返回响应。
-
不管是请求前函数、视图或错误处理程序,都会返回一个响应值,并被转换为 Response 对象。
-
任何 after_this_request() 装饰的函数都会被调用,然后被清除。
-
任何 after_request() 装饰的函数都会被调用,它们可以 修改响应对象。
-
会话被保存,使用应用程序的:attr:~.Flask.session_interface 装饰 函数来持久化任何已修改的会话数据。
-
request_finished 信号被发送。
-
如果到目前为止的任何步骤引发了一个异常,并且没有被错误处理函数处 理,那么现在会被处理。 HTTP 异常会使用对应的状态代码作为响应,其他的异常被转换为一个通用的 500 响应。 got_request_exception 信号被发送。
-
响应对象的状态、头部信息和正文被返回给 WSGI 服务器。
-
任何 teardown_request() 装饰的函数都被调用。
-
request_tearing_down 信号被发送。
-
请求上下文被弹出, request 和 session 不再可用。
-
任何 teardown_appcontext() 的装饰函数都被调用。
-
appcontext_tearing_down 信号被发送。
-
应用上下文被弹出, current_app 和 g 不再可用。
-
appcontext_popped 信号被发送。
还有更多的装饰器和定制点,但它们并不是每个请求生命周期都有。它们更多的是针对在请求过程中可能使用的某些东西,如模板、构建URL 或处理 JSON 数据。
二、钩子函数
上文提到了多个Flask 提供的多个钩子函数,这些钩子函数允许你在请求处理的不同阶段插入自定义逻辑。以下是一些常用的 Flask 钩子函数的用法:
-
before_first_request
:- 在处理第一个请求之前执行一次,通常用于初始化应用。
pythonfrom flask import Flask app = Flask(__name__) @app.before_first_request def before_first_request(): print("This runs before the first request.")
-
before_request
:- 在每次请求之前执行,可用于执行一些全局的预处理工作。
pythonfrom flask import Flask app = Flask(__name__) @app.before_request def before_request(): print("This runs before each request.")
-
after_request
:- 在每次请求之后执行,可用于修改响应对象。
pythonfrom flask import Flask app = Flask(__name__) @app.after_request def after_request(response): print("This runs after each request.") return response
-
teardown_request
:- 在每次请求之后执行,无论是否发生异常。通常用于清理资源。
pythonfrom flask import Flask app = Flask(__name__) @app.teardown_request def teardown_request(exception): print("This runs after each request, even if an exception occurred.")
-
before_render_template
:- 在渲染模板之前执行,可以用于在模板渲染之前注入一些全局数据。
pythonfrom flask import Flask, render_template app = Flask(__name__) @app.before_render_template def before_render_template(template, context): print("This runs before rendering the template.") context['global_variable'] = 'I am a global variable.'
-
template_rendered
:- 在模板渲染之后执行,用于执行一些与模板渲染相关的操作。
pythonfrom flask import Flask, render_template app = Flask(__name__) @app.template_rendered def template_rendered(template, context): print("This runs after rendering the template.")
-
url_value_preprocessor
:- 注册 URL 变量预处理函数,可以在请求处理之前对 URL 变量进行处理。
pythonfrom flask import Flask, url_for app = Flask(__name__) @app.url_value_preprocessor def url_value_preprocessor(endpoint, values): print("This runs before processing the URL values.") # You can modify the values dictionary here.
这只是一小部分 Flask 钩子函数的示例,Flask 提供的钩子函数非常灵活,你可以根据需要选择合适的钩子来插入自定义逻辑。