Flask 请求的生命周期

一、请求生命周期

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 钩子函数的用法:

  1. before_first_request

    • 在处理第一个请求之前执行一次,通常用于初始化应用。
    python 复制代码
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.before_first_request
    def before_first_request():
        print("This runs before the first request.")
  2. before_request

    • 在每次请求之前执行,可用于执行一些全局的预处理工作。
    python 复制代码
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.before_request
    def before_request():
        print("This runs before each request.")
  3. after_request

    • 在每次请求之后执行,可用于修改响应对象。
    python 复制代码
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.after_request
    def after_request(response):
        print("This runs after each request.")
        return response
  4. teardown_request

    • 在每次请求之后执行,无论是否发生异常。通常用于清理资源。
    python 复制代码
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.teardown_request
    def teardown_request(exception):
        print("This runs after each request, even if an exception occurred.")
  5. before_render_template

    • 在渲染模板之前执行,可以用于在模板渲染之前注入一些全局数据。
    python 复制代码
    from 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.'
  6. template_rendered

    • 在模板渲染之后执行,用于执行一些与模板渲染相关的操作。
    python 复制代码
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.template_rendered
    def template_rendered(template, context):
        print("This runs after rendering the template.")
  7. url_value_preprocessor

    • 注册 URL 变量预处理函数,可以在请求处理之前对 URL 变量进行处理。
    python 复制代码
    from 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 提供的钩子函数非常灵活,你可以根据需要选择合适的钩子来插入自定义逻辑。

相关推荐
你的人类朋友3 小时前
说说签名与验签
后端
databook3 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室4 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三5 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试
canonical_entropy7 小时前
AI时代,我们还需要低代码吗?—— 一场关于模型、演化与软件未来的深度问答
后端·低代码·aigc
颜如玉7 小时前
HikariCP:Dead code elimination优化
后端·性能优化·源码
考虑考虑8 小时前
Jpa使用union all
java·spring boot·后端
用户2519162427119 小时前
Python之语言特点
python
bobz9659 小时前
virtio vs vfio
后端
刘立军9 小时前
使用pyHugeGraph查询HugeGraph图数据
python·graphql