• flask 源码专题(九):flask扩展点


    1. 信号(源码)

    • 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作。

      pip3 install blinker 
      

    2. 根据flask项目的请求流程来进行设置扩展点

    • 中间件

      # 代码示例
      
      from flask import Flask,render_template
      
      app = Flask(__name__)
      
      
      @app.route('/index')
      def index():
          return render_template('index.html')
      
      
      @app.route('/order')
      def order():
          return render_template('order.html')
      
      
      class MyMiddleware(object):
          def __init__(self,old_app):
              self.wsgi_app = old_app.wsgi_app
      
          def __call__(self, *args, **kwargs):
              print('123')
              result = self.wsgi_app(*args, **kwargs)
              print('456')
              return result
      
      app.wsgi_app = MyMiddleware(app)
      
      if __name__ == '__main__':
          app.run()
      
    • 当app_ctx被push到local中栈之后,会触发appcontext_pushed信号,之前注册在这个信号中的方法,就会被执行。

      # 代码示例
      
      from flask import Flask,render_template
      from flask import signals
      
      app = Flask(__name__)
      
      @signals.appcontext_pushed.connect
      def f1(arg):
          print('appcontext_pushed信号f1被触发',arg)
      
      @signals.appcontext_pushed.connect
      def f2(arg):
          print('appcontext_pushed信号f2被触发',arg)
      
      @app.route('/index')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
          # app.__call__
      
      
    • 执行before_first_request扩展

      # 代码示例
      
      from flask import Flask,render_template
      
      app = Flask(__name__)
      
      @app.before_first_request
      def f2():
          print('before_first_requestf2被触发')
      
      @app.route('/index')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • request_started信号

      # 代码示例
      
      from flask import Flask,render_template
      from flask import signals
      app = Flask(__name__)
      
      @signals.request_started.connect
      def f3(arg):
          print('request_started信号被触发',arg)
      
      @app.route('/index')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • url_value_processor

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      
      @app.url_value_preprocessor
      def f5(endpoint,args):
          print('f5')
      
      @app.route('/index/')
      def index():
          print('index')
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • before_reuqest

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @app.before_request
      def f6():
          g.xx = 123
          print('f6')
      
      @app.route('/index/')
      def index():
          print('index')
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • 视图函数

    • before_render_template / rendered_template

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @signals.before_render_template.connect
      def f7(app, template, context):
          print('f7')
      
      @signals.template_rendered.connect
      def f8(app, template, context):
          print('f8')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
      
    • after_request

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @app.after_request
      def f9(response):
          print('f9')
          return response
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • request_finished

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @signals.request_finished.connect
      def f10(app,response):
          print('f10')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • got_request_exception

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @app.before_first_request
      def test():
          int('asdf')
      
      @signals.got_request_exception.connect
      def f11(app,exception):
          print('f11')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • teardown_request

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @app.teardown_request
      def f12(exc):
          print('f12')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • request_tearing_down

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @signals.request_tearing_down.connect
      def f13(app,exc):
          print('f13')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
    • appcontext_popped

      # 代码示例
      
      from flask import Flask,render_template,g
      from flask import signals
      app = Flask(__name__)
      
      @signals.appcontext_popped.connect
      def f14(app):
          print('f14')
      
      @app.route('/index/')
      def index():
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          print('order')
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      
      
    • 扩展:flash

      flash存值之后只能取一次

      # 代码示例
      
      from flask import Flask,render_template,flash,get_flashed_messages,session
      from flask import signals
      app = Flask(__name__)
      app.secret_key = 'iuknsoiuwknlskjdf'
      
      @app.route('/index/')
      def index():
          # flash('123')
          session['k1'] = 123
          return render_template('index.html')
      
      @app.route('/order')
      def order():
          # messages = get_flashed_messages()
          # print(messages)
          val = session['k1']
          del session['k1']
          print(val)
          return render_template('order.html')
      
      if __name__ == '__main__':
          app.run()
      

    总结:

    • 关于flask内部共有14+个扩展点用于我们对flask框架内部进行定制,其中有:9个是信号。
    # 源码示例
    template_rendered = _signals.signal("template-rendered") before_render_template = _signals.signal("before-render-template") request_started = _signals.signal("request-started") request_finished = _signals.signal("request-finished") request_tearing_down = _signals.signal("request-tearing-down") got_request_exception = _signals.signal("got-request-exception") appcontext_tearing_down = _signals.signal("appcontext-tearing-down") appcontext_pushed = _signals.signal("appcontext-pushed") appcontext_popped = _signals.signal("appcontext-popped") message_flashed = _signals.signal("message-flashed")
    执行顺序
    2. request_started = _signals.signal('request-started')                # 请求到来前执行
    5. request_finished = _signals.signal('request-finished')              # 请求结束后执行
    3. before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
    4. template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
                     
    发生在2/3/4/5或不执行 got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
                     
    6. request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
    7. appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)     
    1. appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求app上下文push时执行
                    
    8. appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行
                    
    message_flashed = _signals.signal('message-flashed')                   # 调用flask在其中添加数据时,自动触发

    自定义信号

     第一步:创建信号

       第二步:将函数注册到信号中: 添加到这个列表

     第三步: 发送信号

     第四步:运行

     具体实现:可参考flask源码,写一个自定义信号

    from flask import Flask,flash
    from flask.signals import _signals
    app = Flask(__name__)
    
    xinhao = _signals.signal("xinhao")#创建信号
    #定义函数
    def wahaha(*args,**kwargs):
        print("111",args,kwargs)
    
    def sww(*args,**kwargs):
        print("222",args,kwargs)
    # 将函数注册到信号中,添加到这个列表
    xinhao.connect(wahaha)
    xinhao.connect(sww)
    
    @app.route("/zzz")
    def zzz():
        xinhao.send(sender='xxx',a1=123,a2=456)  #触发这个信号,执行注册到这个信号列表中的所有函数,此处的参数个数需要与定义的函数中的参数一致
        return "发送信号成功"
    
    if __name__ == '__main__':
        app.run(debug=True)
        
    #打印结果
    # 111 (None,) {'sender': 'xxx', 'a1': 123, 'a2': 456}
    # 222 (None,) {'sender': 'xxx', 'a1': 123, 'a2': 456}
     
  • 相关阅读:
    Windows环境下多版本JDK切换
    科学记数法数字转换/保留数值小数点位数(数字格式化)
    解析Excel数据
    odoo 配置文件参数大全
    odoo10 addon开发流程
    odoo10源码 windows环境安装
    【12】Django 中间件
    【10】Cookie和Session
    django-debug-toolbar
    爬虫系列之mongodb
  • 原文地址:https://www.cnblogs.com/qiu-hua/p/12637765.html
Copyright © 2020-2023  润新知