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

相关推荐
秀儿还能再秀33 分钟前
机器学习——简单线性回归、逻辑回归
笔记·python·学习·机器学习
阿_旭2 小时前
如何使用OpenCV和Python进行相机校准
python·opencv·相机校准·畸变校准
幸运的星竹2 小时前
使用pytest+openpyxl做接口自动化遇到的问题
python·自动化·pytest
杨哥带你写代码2 小时前
网上商城系统:Spring Boot框架的实现
java·spring boot·后端
camellias_2 小时前
SpringBoot(二十一)SpringBoot自定义CURL请求类
java·spring boot·后端
背水2 小时前
初识Spring
java·后端·spring
晴天飛 雪2 小时前
Spring Boot MySQL 分库分表
spring boot·后端·mysql
weixin_537590452 小时前
《Spring boot从入门到实战》第七章习题答案
数据库·spring boot·后端