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 提供的钩子函数非常灵活,你可以根据需要选择合适的钩子来插入自定义逻辑。

相关推荐
mldong3 小时前
C# 开发者也有自己的轻量工作流引擎了:NuGet 装包,5 分钟跑通一条审批流
后端·c#·.net
爱学堂IT分享5 小时前
鹤翔老师pmp项目管理培训认证考试课 (直播录播题库送学时证明)【共58课时】-51CTO学堂
后端
benchmark_cc5 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库5 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
码事漫谈6 小时前
类型即世界:一个 C++ 程序员的本体论入门
后端
2601_962382436 小时前
python快乐编程网络爬虫课后答案
python·网络爬虫·学习工具·课后答案·刷题app
Rain的Java大神之路7 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
鹏哥带你干乡墅7 小时前
优选乡墅赋能培训平台如何帮助提升乡村建设?
大数据·人工智能·python
veminhe8 小时前
python调用接口获取网络信息
python
Allen_LVyingbo8 小时前
医疗AI基础2026-构建可靠智能体的编程路径(上)
大数据·数据库·人工智能·python·自动化