• Flask 学习67.钩子函数before_request 和 before_first_request 的使用 上海


    前言

    学过pytest框架的肯定知道什么叫钩子(hook)函数, 钩子函数的作用是在程序运行的过程中插入一段代码做一些事情。

    四个钩子

    请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:

    before_first_request 在对应用程序实例的第一个请求之前注册要运行的函数, 只会执行一次
    before_request 在每次请求前执行,如果在某修饰的函数中返回了一个响应,视图函数将不再被调用
    after_request 如果没有抛出错误,在每次请求后执行接受一个参数:视图函数作出的响应,在此函数中可以对响应值在返回之前做最后一步修改处理,需要将参数中的响应在此参数中进行返回
    teardown_request: 每一个请求之后绑定一个函数,即使遇到了异常。。接受一个参数:错误信息,如果有相关错误抛出

    before_first_request

    before_first_request 在第一次请求之前执行

    @app.before_first_request
    def first_request():
        print('first request: hello ------------------')
    

    使用示例

    from flask import Flask, request, g
    app = Flask(__name__)
    
    
    @app.before_first_request
    def first_request():
        print('first request: hello ------------------')
    
    
    @app.route('/login')
    def login():
        user = request.args.get('username')
        return {'msg': 'ok', 'admin': user}
    
    
    @app.route('/index')
    def index():
        return {'msg': 'ok'}
    
    
    if __name__ == '__main__':
        app.run()
    
    

    before_first_request 在项目启动后,第一次请求之前仅执行一次

    before_request 和 after_request

    before_request 在每次请求前执行,如果在某修饰的函数中返回了一个响应,视图函数将不再被调用
    after_request 如果没有抛出错误,在每次请求后执行接受一个参数

    before_request 可以用于拦截请求数据,比如打印一些日志

    @app.before_request
    def pre_request():
        app.logger.debug(f'path:{request.path}')
        app.logger.debug(f'args:{dict(request.args)}')
        app.logger.debug(f'headers:{request.headers}')
        app.logger.debug(f'cookies:{dict(request.cookies)}')
        app.logger.debug(f'json:{request.json}')
    

    完整的示例

    from flask import Flask, request, g, abort
    app = Flask(__name__)
    
    
    @app.before_request
    def pre1_request():
        print('pre1_request')
    
    
    @app.before_request
    def pre2_request():
        print('pre2_request')
    
    
    @app.after_request
    def aft1_request(response):
        print('aft1_request')
        return response
    
    
    @app.after_request
    def aft2_request(response):
        print('aft2_request')
        return response
    
    
    @app.teardown_request
    def teardown(exc=None):
        print('teardown_request')
    
    
    @app.route('/login')
    def login():
        user = request.args.get('username')
        return {'msg': 'ok', 'admin': user}
    
    
    @app.route('/index')
    def index():
        return {'msg': 'ok'}
    
    
    if __name__ == '__main__':
        app.run()
    
    

    执行顺序是

    pre1_request
    pre2_request
    aft2_request
    aft1_request
    teardown_request
    

    before_request 先注册的先执行,after_request先注册的后执行。
    after_request 被触发的前提是没有异常抛出; 或者异常被 errorhandler 接住并处理

    比如abort(400)异常被errorhandler 接住并处理,那么after_request也会执行。

    @app.route('/index')
    def index():
        abort(400)
    

    teardown_request

    teardown_request 就和其余的三个不太一样了. 严格的来说 teardown_request 没有固定的执行位置.
    因为他直接和请求上下文环境挂钩. 只有在请求上下文被 pop 出请求栈的时候才会触发 teardown_request, 所以即使之前有抛出错误的时候也会都会被执行, 执行完后返回 response.

    @app.teardown_request
    def teardown(exc=None):
        print('teardown_request')
    

    总的来说, 这几个装饰器装饰的方法执行的先后为 before_request -> errorhandler -> after_request
    teardown_request 在将当前请求 pop 出请求栈的时候执。

  • 相关阅读:
    POJ2104 K-th Number Range Tree
    BZOJ 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复(最大生成树)
    BZOJ 3391: [Usaco2004 Dec]Tree Cutting网络破坏(搜索)
    BZOJ 3412: [Usaco2009 Dec]Music Notes乐谱(离线处理)
    BZOJ 3410: [Usaco2009 Dec]Selfish Grazing 自私的食草者(贪心)
    BZOJ 3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)
    BZOJ 3402: [Usaco2009 Open]Hide and Seek 捉迷藏(最短路)
    BZOJ 3479: [Usaco2014 Mar]Watering the Fields(最小生成树)
    BZOJ 3432: [Usaco2014 Jan]Cross Country Skiing (二分+染色法)
    BZOJ 3299: [USACO2011 Open]Corn Maze玉米迷宫(BFS)
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/16673124.html
Copyright © 2020-2023  润新知