• day92 请求扩展 请求上下文


    请求扩展

    from flask import Flask,render_template
    
    app=Flask(__name__)
    
    '''
    @app.before_request:
    是在真正的响应函数之前执行。
    可以有多个,当有多个的时候执行顺序是谁在前面就谁先执行
    只要有一个before_request有返回值,那么后面所有的before_request都不会执行,真正的响应函数也不会执行
    '''
    @app.before_request
    def befor_process():
        print("befor_process0")
        # return "tt"
    
    @app.before_request
    def befor_process1():
        print("befor_process1")
    
    '''
    @app.after_request:
    after_request是在真正响应函数之后执行的。
    他可以有多个,当有多个的时候执行顺序为,谁在前面谁后执行。
    before_request的有没有返回值不会影响到after_request的执行
    '''
    @app.after_request
    def after_process(response):
        print("我是请求之后1")
        return response
    
    @app.after_request
    def after_process1(response):
        print("我是请求之后2")
        return response
    
    '''
    @app.before_first_request:
    在项目启动后第一次接收到请求,就会执行这个方法。以后不会执行
    '''
    @app.before_first_request
    def first():
        print(123)
    
    '''
    @app.teardown_request:
    不管有没有错误,都会执行teardown_request
    如果没有错误,错误值为None,如果有错误,直接传递给被装饰的函数
    '''
    @app.teardown_request
    def tre(e):
        print("e",e)
    
    '''
    @app.errorhandler(错误码):
    如果没有该错误码出现,地下的函数不会执行,如果有该错误码的错误出现就会执行下面的函数,不会让错误暴露给用户
    '''
    @app.errorhandler(500)
    def error_handler(*args,**kwargs):
        print(*args,**kwargs)
        return "500错误"
    
    @app.errorhandler(404)
    def errr(e):
        return render_template("index404.html")
    
    '''
    @app.template_global():
    标签 可以在路由返回的页面中使用 全局的 都可以使用
    '''
    @app.template_global()
    def sb(a1,a2,a3):
        return a1+a2+a3
    '''
    @app.template_filter():
    过滤器 可以在路由返回的页面中使用 全局的 都可以使用
    '''
    @app.template_filter()
    def sb1(a1,a2,a3):
        return a1+a2+a3
    
    @app.route("/index")
    def index():
        print("index")
        return render_template("index.html")
    
    if __name__ == '__main__':
        app.run()
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>okok</h1>
    <h1>{{sb(1,2,3)}}</h1>
    <h1>{{"tank"|sb1(" is ","sb")}}</h1>
    </body>
    </html>
    

    index404.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>404错误页面</h1>
    </body>
    </html>
    

    中间件

    '''
    1 当执行app.run()方法的时候,最终执行run_simple,最后执行app(),也就是在执行app.__call__方法
    2 在__call__里面,执行的是self..wsgi_app(),那么希望在执行他本身的wsgi之前做点事情
    3 所有我们先用MyMiddleware类中__init__,保存之前的wsgi,然后我们将app.wsgi转化成MyMiddleware的对象
    4 把原来的wsgi.app替换为自定义的
    '''
    from flask import Flask
    app=Flask(__name__)
    
    class MyMiddleware(object):
        def __init__(self,old_wsgi_app):
            self.old_wsgi_app=old_wsgi_app
    
        def __call__(self, environ, start_response):
            print("123")
            ret=self.old_wsgi_app(environ, start_response)
            print("456")
            return ret
    
    @app.route('/')
    def index():
        return "ok"
    
    if __name__ == '__main__':
        app.wsgi_app=MyMiddleware(app.wsgi_app)
        app.run()
    

    偏函数

    将所作用的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。

    简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

    from functools import partial
    
    def test(a,b,c):
        return a+b+c
    
    tes=partial(test,1,2,4)
    #用partial可以得到一个带了参数的函数对象
    print(tes())
    
    tes1=partial(test,1,2)
    print(tes1(c=5))
    
    

    蓝图

    -app01
    	--__init__.py
    	--order.py
    	--user.py
    -run.py
    

    init.py

    from flask import Flask
    app=Flask(__name__)
    
    from app01 import user
    from app01 import order
    
    @app.before_request
    def tt1():
        print("我是app的befor——request")
    
    
    app.register_blueprint(user.us)
    app.register_blueprint(order.ord)
    

    order.py

    from flask import Blueprint
    ord=Blueprint("order",__name__)
    
    @ord.route("/order")
    def order():
        return "order"
    

    user.py

    from flask import Blueprint,url_for
    us=Blueprint("user",__name__)
    
    @us.before_request
    def beofor_req():
        print("我是user里面的befor_request")
    
    @us.route("/user")
    def index():
        print(url_for("user.order"))
        print(url_for("order.order"))
        return "index"
    
    @us.route("/tt")
    def order():
        return "455"
    

    run.py

    from app01 import app
    
    if __name__ == '__main__':
        app.run()
    

    loacal对象的补充

    # 启动一个多线程,多线程修改一个全局的值,并且要求打印,它自己修改成功之后的那个值
    from threading import Thread
    import time
    from threading import local
    
    # 利用local
    '''
    cxw = local()
    def task(arg):
        cxw.value = arg
        # cxw[线程id][value]=arg
        time.sleep(1)
        # cxw[线程id][value]
        print(cxw.value)
    '''
    
    from threading import get_ident
    
    # 用函数的形式模拟local()对象
    '''
    storage={}
    def set(k,v):
        ident=get_ident()
        if ident in storage:
            storage[ident][k]=v
        else:
            storage[ident]={k:v}
    
    def get(k):
        ident=get_ident()
        return storage[ident][k]
    
    def task(arg):
        set("val",arg)
        time.sleep(1)
        v=get('val')
        print(v)
    '''
    
    # 面向对象版
    '''
    class Local:
        storage = {}
        def set(self,k,v):
            ident = get_ident()#获取线程协程的id
            if ident in Local.storage:
                Local.storage[ident][k] = v
            else:
                Local.storage[ident] = {k: v}
    
        def get(self,k):
            ident = get_ident()
            return Local.storage[ident][k]
    obj=Local()
    def task(arg):
        obj.set("val", arg)
        time.sleep(1)
        v = obj.get('val')
        print(v)
    '''
    
    
    # 面向对象版的getattr和setattr实现,,每个local对象都有他自己的storage
    
    class Local(object):
        def __init__(self):
            object.__setattr__(self, "storage", {})
            # storage={}
    
        def __setattr__(self, k, va):
            ident = get_ident()
            if ident in self.storage:
                self.storage[ident][k] = va
            else:
                self.storage[ident] = {k: va}
    
        def __getattr__(self, k):
            ident = get_ident()
            return self.storage[ident][k]
    
    
    obj = Local()
    
    
    def task(arg):
        obj.va = arg
        time.sleep(1)
        print(obj.va)
    
    
    for i in range(10):
        t = Thread(target=task, args=(i,))
        t.start()
    
    

    请求上下文

    1 执行 ctx = self.request_context(environ) 将请求相关的放入ctx
    
    
    2 ctx.push 方法,把cxt放入到Local对象中的stroage[线程或者协程id][stark]=[ctx,]
    
    3  response = self.full_dispatch_request()这个是请求扩展和响应函数的内容
    
    4 在上述的3中我们可以在任意位置调用 resquest
    
    5 当我们调用request.methons的时候是怎么获取到的?从第二步中存的Local把ctx取出来
    
    6 在ctx在取request
    
    7 然后再从request取methons
    
    
  • 相关阅读:
    移位运算符
    java 链表数据结构
    log4j.properties配置详解
    java异常面试题
    QuickHit项目(输出字符串游戏)
    适配器模式
    java 单例
    sql索引的填充因子多少最好,填充因子的作用?
    聚焦索引和非聚焦索引的区别
    二叉树。。。。
  • 原文地址:https://www.cnblogs.com/zqfzqf/p/12392243.html
Copyright © 2020-2023  润新知