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 會先執行。flask
查看 before_request :app
1 @setupmethod 2 def before_request(self, f): 3 self.before_request_funcs.setdefault(None, []).append(f) 4 return f
首先要知道在腳本加載時,被裝飾器裝飾的函數會被做爲參數傳入裝飾器函數,在上面示例中也就是會將 xx 函數做爲 before_request 函數的參數 f 傳入。能夠看到該裝飾器函數就很簡單兩行,把函數 f 句柄添加到 app.before_request_funcs 列表中,對應示例中就是將 xx 函數的句柄添加到了 before_request_funcs 中。ide
緊接着,在請求到來時,會執行 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)
進到第 7 行的 full_dispatch_request 方法:url
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)
再進到第 5 行的 preprocess_request 方法:spa
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
看到第 10 行,從 self.before_request_funcs 拿到以前存入的方法,也就是也就是上面被 before_request 裝飾器裝飾的函數對應示例中的 xx ,接着在 13-16 行循環執行全部方法,若是有返回值則直接返回,到這裏 before_request 的執行原理也就明瞭了。緊接着 flask.app.Flask.full_dispatch_request 中第 5 行接收到返回值,第 六、7 行判斷若是返回值若是爲空,才執行 self.dispatch_request 方法。而 self.dispatch_request 方法正是用來執行視圖函數的。因此得出結論:若是 before_request 裝飾器裝飾的函數有返回值,那麼將不會繼續執行視圖函數。3d