zoukankan      html  css  js  c++  java
  • python框架之Flask(5)-@app.before_request原理

    示例

    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.before_request
    def xx():
        pass
    
    
    @app.route('/')
    def index():
        return 'index'
    
    
    if __name__ == '__main__':
        app.run()

    看如上代码,如果此时请求视图函数 index ,在视图函数执行之前, @app.before_request 装饰的函数在这里也就是 xx 会先执行。

    源码

    查看 before_request :

    1 @setupmethod
    2 def before_request(self, f):
    3     self.before_request_funcs.setdefault(None, []).append(f)
    4     return f
    flask.app.Flask.before_request

    首先要知道在脚本加载时,被装饰器装饰的函数会被作为参数传入装饰器函数,在上面示例中也就是会将 xx 函数作为 before_request 函数的参数 f 传入。可以看到该装饰器函数就很简单两行,把函数 f 句柄添加到 app.before_request_funcs 列表中,对应示例中就是将 xx 函数的句柄添加到了 before_request_funcs 中。

    紧接着,在请求到来时,会执行 app.wsgi_app 方法:

     1 def wsgi_app(self, environ, start_response):
     2     ctx = self.request_context(environ)
     3     error = None
     4     try:
     5         try:
     6             ctx.push()
     7             response = self.full_dispatch_request()
     8         except Exception as e:
     9             error = e
    10             response = self.handle_exception(e)
    11         except:
    12             error = sys.exc_info()[1]
    13             raise
    14         return response(environ, start_response)
    15     finally:
    16         if self.should_ignore_error(error):
    17             error = None
    18         ctx.auto_pop(error)
    flask.app.Flask.wsgi_app

    进到第 7 行的 full_dispatch_request 方法:

     1 def full_dispatch_request(self):
     2     self.try_trigger_before_first_request_functions()
     3     try:
     4         request_started.send(self)
     5         rv = self.preprocess_request()
     6         if rv is None:
     7             rv = self.dispatch_request()
     8     except Exception as e:
     9         rv = self.handle_user_exception(e)
    10     return self.finalize_request(rv)
    flask.app.Flask.full_dispatch_request

    再进到第 5 行的 preprocess_request 方法:

     1 def preprocess_request(self):
     2     bp = _request_ctx_stack.top.request.blueprint
     3 
     4     funcs = self.url_value_preprocessors.get(None, ())
     5     if bp is not None and bp in self.url_value_preprocessors:
     6         funcs = chain(funcs, self.url_value_preprocessors[bp])
     7     for func in funcs:
     8         func(request.endpoint, request.view_args)
     9 
    10     funcs = self.before_request_funcs.get(None, ())
    11     if bp is not None and bp in self.before_request_funcs:
    12         funcs = chain(funcs, self.before_request_funcs[bp])
    13     for func in funcs:
    14         rv = func()
    15         if rv is not None:
    16             return rv
    flask.app.Flask.preprocess_request

    看到第 10 行,从 self.before_request_funcs 拿到之前存入的方法,也就是也就是上面被 before_request 装饰器装饰的函数对应示例中的 xx ,接着在 13-16 行循环执行所有方法,如果有返回值则直接返回,到这里 before_request 的执行原理也就明了了。紧接着 flask.app.Flask.full_dispatch_request 中第 5 行接收到返回值,第 6、7 行判断如果返回值如果为空,才执行 self.dispatch_request 方法。而 self.dispatch_request 方法正是用来执行视图函数的。所以得出结论:如果 before_request 装饰器装饰的函数有返回值,那么将不会继续执行视图函数。

  • 相关阅读:
    [No0000159]C# 7 中的模范和实践
    [No0000158]思维模型1-20
    [No000014B]Office-PPT设置默认打开视图
    [No000014C]让大脑高效运转的24个技巧
    [No000014A]Linux简介与shell编程
    [No000014D]chrome console 调试 引入 jquery等外部库
    [No0000157].net core项目中拼音,excel,pdf处理库
    [No0000156]天干地支-狗年我懂,戊戌二字怎么来的?
    [No0000155]为什么32位机器最大只能用到4GB内存
    [No0000154]详解为什么32位系统只能用4G内存.
  • 原文地址:https://www.cnblogs.com/zze46/p/10141668.html
Copyright © 2011-2022 走看看