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("",args,kwargs) def sww(*args,**kwargs):
print("",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}
 

flask 源码专题(九):flask扩展点的更多相关文章

  1. Flask源码解读--所有可扩展点

    一.前言 flask中有很多可扩展点(笔者这样称呼),其中包含了信号和请求钩子,这些信号和钩子有什么用呢?其主要作用用于帮助我们进行程序的耦合性,当然还可以让我们自定义一些行为.话不多说,通过阅读源码 ...

  2. flask 源码专题(五):SqlAlchemy 中操作数据库时session和scoped_session的区别

    1原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalc ...

  3. flask 源码专题(二):请求上下文与全文上下文

    源码解析 0. 请求入口 if __name__ == '__main__': app.run() def run(self, host=None, port=None, debug=None, lo ...

  4. 08 Flask源码剖析之flask拓展点

    08 Flask源码剖析之flask拓展点 1. 信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 2. 根据flas ...

  5. flask 源码专题(十一):LocalStack和Local对象实现栈的管理

    目录 04 LocalStack和Local对象实现栈的管理 1.源码入口 1. flask源码关于local的实现 2. flask源码关于localstack的实现 3. 总结 04 LocalS ...

  6. flask 源码专题(八):路由加载

    1.示例代码 from flask import Flask app = Flask(__name__,static_url_path='/xx') @app.route('/index') def ...

  7. flask 源码专题(六):session处理机制

    前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活 ...

  8. flask 源码专题(一):app.run()的背后

    当我们用Flask写好一个app后, 运行app.run()表示监听指定的端口, 对收到的request运行app生成response并返回. 现在分析一下, 运行app.run()后具体发生了什么事 ...

  9. flask 源码专题(十):flash源码研究

    flash源码 def flash(message, category="message"): flashes = session.get("_flashes" ...

随机推荐

  1. CSS中的百分比(%)如何使用???

    除了height以外垂直方向上的margin-top(bottom)或者padding-top(bottom)的百分比取值都是相对于父元素的宽度 在默认的content-box盒模型下元素的width ...

  2. 一文读懂Redis的四种模式,单机、主从、哨兵、集群

    少点代码,多点头发 本文已经被GitHub收录,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 入职第一周,我被坑了 最近刚入职 ...

  3. 12个Python游戏中的龙穴探险,快速掌握基础,其实很简单

    越来越多的人学习python编程,但更多的人,拿着教程却不知道该怎么学. 今天我给大家举一个例子,是我自己学习python时,用到的方法.     首先,我是一名普通的程序员,相对于十几年开发经验的程 ...

  4. WeChair项目Alpha冲刺(10/10)

    团队项目进行情况 1.昨日进展    Alpha冲刺第十天 昨日进展: 前端:安排页面美化,设计实名认证 后端:更新dao层代码 数据库:修改数据表属性,与后端部署数据库交互 2.今日安排 前端:继续 ...

  5. 定量度量程序复杂度的McCabe方法

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 请画出下面代码的 ...

  6. js中.bind()和.call()用法讲解

    var option = { ti : 8, it(){ return this.ti; } } 这里又一个option对象,it()方法里的this指的就是option对象的上下文. console ...

  7. python 2 与python 3区别汇总

    python 2 与python 3区别汇总 一.核心类差异1. Python3 对 Unicode 字符的原生支持.Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类 ...

  8. 一条update SQL语句是如何执行的

    一条更新语句的执行过程和查询语句类似,更新的流程涉及两个日志:redo log(重做日志)和binlog(归档日志).比如我们要将ID(主键)=2这一行的值加(c:字段)1,SQL语句如下: upda ...

  9. 02 [掌握] redis详情命令

    1,常用命令 keys * 获取所有的key select 0 选择第一个库 move myString 1 将当前的数据库key移动到某个数据库,目标库有,则不能移动 flushdb 清除指定库 r ...

  10. 为Linux主机安装图形化桌面环境

    本文主要介绍在Linux实例中,centos 7 以及ubutun 14如何安装图形化桌面环境. CentOS 7 此处以安装MATE桌面环境为例,步骤如下. 说明:在安装重启后,如果卡在启动页面,需 ...