请求扩展、中间件、请求上下文源码

一、请求扩展

1 before_first_request

   当项目启动后,接收到的第一个请求,就会执行before_first_request装饰的函数,执行顺序:谁先注册就谁先执行

2 before_request

   请求没有经过响应函数的时候,会执行before_request装饰的函数,谁先注册谁先执行

    只要有一个函数有返回值,后面的所有before_request都不会执行,且响应函数也不会执行。其有没有返回值都不会影响after_request的执行

3 after_request

   是再before_request与响应函数执行后执行。他必须接收响应参数(response或res),并且要把响应(response或res)返回。执行顺序是:谁先注册后执行

#flask里面的请求扩展相当于django中的中间件
from flask import Flask,request

app = Flask(__name__)

# 1 执行响应函数之前,相当于django中的process_request,再执行响应函数执行一些事情
# 2 请求执行之前,before_request装饰的函数是,谁先注册谁先执行
# 3 如果befor_request中有返回值,那后面的befor_request不会执行,而且响应函数也不会执行.但是after_rquest都会执行
@app.before_request
def before1(*args,**kwargs):
    print('参数',*args,**kwargs)
    print("我是befor1")
    return "ok"

@app.before_request
def before2():
    print("我是befor2")

# 1、响应函数之后执行的,process_response,就是在执行响应函数之后执行的
# 2、after_request必须接收一个参数,参数为response对象,而且必须返回
# 3、after_request的执行顺序,是谁先注册,后执行
@app.after_request
def after1(response):
    print("响应后的参数",response)
    print("我是after1")
    return response

@app.after_request
def after2(response):
    print("我是after2")
    return response

# 项目启动后接收到的第一个请求后所要执行的函数,这是整个项目的第一次,
# 真的一次,不是和哪个浏览器的第一次有关,就是,你请求过了,再换了浏览器它也不执行
@app.before_first_request
def first():
    print("我是第一次")

@app.route("/")
def index():
    print("我是响应函数")
    return "ok"

if __name__ == '__main__':
    app.run()

 结果

 

二、请求上下文 源码:

进 __call__

   def __call__(self, environ, start_response):
 
        return self.wsgi_app(environ, start_response)

进 上面的 wsgi_ap

    def wsgi_app(self, environ, start_response):
  
        # ctx就是RequestContext的一个对象,里面包含了请求相关的东西
       1、 ctx = self.request_context(environ)
        error = None
        try:
            try:
                # 就把ctx放到Local对象里面了
              2、 ctx.push()
                # 请求扩展以及响应函数
               3、response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)
    def __call__(self, environ, start_response):
 
        return self.wsgi_app(environ, start_response)
    def __repr__(self):
        return "<%s %r>" % (self.__class__.__name__, self.name)

2、 进 .push()

进 上面标红的 

图888

第一次执行app.__call__后, 这些全部都在内存里了  因为这些是 全局的  

进 上面标红的 

3、进上面的  .full_dispatch_request()

 进 上面 标红

 进 @app.before_first_request

标绿的意思时

 进上面标绿的 

 继续

 

进图888中 标黄的LocalProxy

 

 进 看 LocalProxy中 的__getattr__ 方法

进 绿色

 上图代码的解释

 

 

 

 进 图888 中的蓝色

 进 上图绿色

 解析

三、请求扩展

4、 teardown_request,一旦遇到错误就会执行,并且把错误传递给teardown_request装饰的函数。

     没有错误也会执行,但是是错误为None,他并不能处理错误,只能记录

01、有错

 02、没错

5、 errorhandle 可以捕获错误,并且对错误做出响应,返回给用户。

     如果你要用errorhandler你必须指定他捕获哪种类型的错误,就必须传错误码,然后就返回值,返回给用户

01、有错

 

 02、没错

 6、template_global()

      相当于django中的标签,只要定义它,就可以再不把函数对象传递模板的情况下,再模板中直接使用。用法:{{函数名()}}

01、向html传函数:方式一

 

 02、向html传函数:方式二

 

 

7、template_filter()

     相当于django中的过滤器,它使用和django中的过滤一样的用,但是它可以接收多个参数,无论是几个。用法:{{要过滤的值|函数名(参数)}}

 

 

四、中间件

from flask import Flask

app = Flask(__name__)
class MyMiddleware:
    def __init__(self,old_wsgi_app):
        self.old_wsgi_app =old_wsgi_app
    def __call__(self, environ, start_response):
        #这befor的befor
        print("开始之前")
        ret = self.old_wsgi_app(environ, start_response)
        #这是after的after
        print("结束之后")
        return ret

@app.route("/")
def index():
    return "ok"


if __name__ == '__main__':
    app.wsgi_app = MyMiddleware(app.wsgi_app)
    app.run()

 

posted @ 2020-03-19 22:58  薛定谔的猫66  阅读(115)  评论(0)    收藏  举报