示例

  1. from flask import Flask
  2.  
  3. app = Flask(__name__)
  4.  
  5. @app.before_request
  6. def xx():
  7. pass
  8.  
  9. @app.route('/')
  10. def index():
  11. return 'index'
  12.  
  13. if __name__ == '__main__':
  14. 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 装饰器装饰的函数有返回值,那么将不会继续执行视图函数。

python框架之Flask(5)-@app.before_request原理的更多相关文章

  1. python框架之Flask(1)-Flask初使用

    Flask是一个基于 Python 开发并且依赖 jinja2 模板和 Werkzeug WSGI 服务的一个微型框架,对于 Werkzeug 本质是 Socket 服务端,其用于接收 http 请求 ...

  2. python框架之Flask(4)-上下文管理

    知识储备 偏函数 作用 偏函数,帮助开发者自动传递参数. 使用 import functools def index(a1, a2): return a1 + a2 # 原来的调用方式 # ret = ...

  3. python框架之Flask基础篇(二)-------- 数据库的操作

    1.flask连接数据库的四步: 倒入第三方数据库扩展包:from flask_sqlalchemy import SQLAlchemy 配置config属性,连接数据库: app.config[&q ...

  4. python框架之Flask

    介绍:Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . WSGl:Web Server Gateway ...

  5. python框架之Flask(3)-Blueprint(蓝图)

    蓝图 用途 给开发者提供清晰的目录结构. 使用 目录结构 1.创建项目. 2.在项目目录下创建与项目名同名文件夹. 3.在 test_prj 文件夹下创建 __init__.py 文件,并在其中实例化 ...

  6. python框架之Flask基础篇(一)

    一.第一个hello world程序 # coding=utf-8 from flask import Flask app = Flask(__name__) @app.route('/') def ...

  7. python框架之Flask基础篇(三)-------- 模版的操作

    1.flask特有的变量和函数: 变量:g.session.request.config 函数:url_for().get_flashed_messages()这个函数注意了啊,记住这是个函数,别忘了 ...

  8. python框架之Flask(2)-路由和视图&Session

    路由和视图 这一波主要是通过看源码加深对 Flask 中路由和视图的了解,可以先回顾一下装饰器的知识:[装饰器函数与进阶] 路由设置的两种方式 # 示例代码 from flask import Fla ...

  9. python框架之Flask(6)-flask-sqlalchemy&flask-script&flask-migrate使用

    整合SQLAlchemy 安装 pip3 install flask-sqlalchemy 简单使用 from flask import Flask from flask_sqlalchemy imp ...

随机推荐

  1. Atitit r2017 r6 doc list on home ntpc.docx

    Atitit r2017 r6 doc list on home ntpc.docx 驱动器 D 中的卷是 p2soft 卷的序列号是 9AD0-D3C8 D:\ati\r2017 v4 raf\r2 ...

  2. Atitit 乌合之众读后感attilax总结 与读后感结构规范总结

    Atitit 乌合之众读后感attilax总结 与读后感结构规范总结 1. 背景概览与鸟瞰overview 1 1.1. 社会背景 与 历史事件背景  与历史时间背景 1 1.2. 书籍简绍 2 1. ...

  3. windows下telnet命令不好用解决方案;

    1.按网上说的windows下打开功能,telnet客户端打钩是必须的: 2.如果还不行,找到telnet.exe:然后把此路径添加到环境变量path下即可: ps:telnet的退出:quit命令:

  4. SQL注入学习资料总结

    转载自:https://bbs.ichunqiu.com/thread-12105-1-1.html  什么是SQL注入 SQL注入基本介绍 结构化查询语言(Structured Query Lang ...

  5. IntelJ idea下lombok 不生效的问题(@Builder等注解不生效的问题)解决,lombok Plugin插件安装

    插件安装方式,在设置setting 中找到plugins.在检索框中检索lom,没有的话点击红框内的search in repositories. 点击install进行安装. 记得安装好了重启ide ...

  6. IDEA阅读spring源码并调试

    目标:搭建起Spring源码阅读和代码调试跟踪的环境,顺便建立一个简单的Demo,能够调试Spring的源代码 本节,主要介绍一下Spring源码阅读和调试的相关环境搭建,并使用MVN创建一个非常简单 ...

  7. IntelliJ IDEA License Server 安装使用 Mac篇

    一.下载 IntelliJ IDEA 是Java开发利器,用社区版不爽,干催就用旗舰版,这个是收费的,需要licence.  IntelliJ IDEA下载地址:https://www.jetbrai ...

  8. <数字签名是什么>笔记

    此篇是看   数字签名是什么?    的理解与笔记 1. 使用非对称密钥发送数据到服务器. 发送方(C端)使用公钥对自己的数据进行加密,接收方(S端)使用私钥解密,即使发送出去的数据被拦截到,也不知道 ...

  9. [Ubuntu] Git可视化比较工具 P4Merge 的安装/配置及使用

    1 下载 下载地址. 链接到上面的下载页后,先找到左边导航的 Clients ,如下图 1 所示. 接着找到 P4Merge: Visual Merge Tool , 如下图 2 所示. 最后,选择好 ...

  10. Sublime Text 3 3143 注册码和遇到的PyV8无法下载问题

    packagecontrol官网:https://packagecontrol.io/installation sublime安装之后,安装Package Control管理插件. sublime3 ...