@buoge
2017-06-16T09:16:19.000000Z
字数 1963
阅读 1718
Python Flask
Flask信号(signals, or event hooking)允许特定的发送端通知订阅者发生了什么( 既然知道发生了什么,那我们可以知道接下来该做什么了)。
Flask提供了一些信号(核心信号)且其它的扩展提供更多的信号。信号是用于通知 订阅者,而不应该鼓励订阅者修改数据。相关信号请查阅文档。
信号依赖于Blinker库。
http://luciferlv.tech/2017/03/17/day0317/
Flask钩子(通常出现在蓝图或应用程序现存的方法中,比如一些内置装饰器,例如 before_request)不需要Blinker库并且允许你改变请求对象(request)或者响应对 象(response)。这些改变了应用程序(或者蓝图)的行为。比如before_request() 装饰器。
信号看起来和钩子做同样的事情。然而在工作方式上它们存在不同。譬如核心的 before_request()处理程序以特定的顺序执行,并且可以在返回响应之前放弃请求 。相比之下,所有的信号处理器是无序执行的,并且不修改任何数据。
from flask import Flask, g, requestapp = Flask(__name__)@app.before_requestdef before_request():print 'before request started'print request.url@app.before_requestdef before_request2():print 'before request started 2'print request.urlg.name="SampleApp"@app.after_requestdef after_request(response):print 'after request finished'print request.urlresponse.headers['key'] = 'value'return response@app.teardown_requestdef teardown_request(exception):print 'teardown request'print request.url@app.route('/')def index():return 'Hello, %s!' % g.nameif __name__ == '__main__':app.run(host='0.0.0.0', debug=True)
我们在全局定义了一个”index_called”信号对象,表示根路径被访问了。然后我们在根路径的请求处理中发出这个信号:
from blinker import Namespacesignals = Namespace()index_called = signals.signal('index-called')
@app.route('/')def index():index_called.send(current_app._get_current_object(), method=request.method)return 'Hello Flask!'
发送信号消息的方法是”send()”,它必须包含一个参数指向信号的发送者。这里我们使用了”current_app._get_current_object()”来获取应用上下文中的app应用对象。怎么,忘了这个”current_app”是什么了?回顾下上一篇吧。这样每次客户端访问根路径时,都会发送”index_called”信号。”send()”方法可以有多个参数,从第二个参数开始是可选的,如果你要提供,就必须是key=value形式。而这个key就可以在订阅回调函数中接收。这个例子中,我们传递了请求的方法。
def log_index_called(sender, method, **extra):print 'URL "%s" is called with method "%s"' % (request.url, method)index_called.connect(log_index_called, app)
将请求地址和方法打印在控制台上。
另外,同核心信号一样,自定义信号的回调函数也可以用装饰器来修饰,上面的代码等同于:
@index_called.connect_via(app)def log_index_called(sender, method, **extra):print 'URL "%s" is called with method "%s"' % (request.url, method)
