@buoge
2017-06-16T17:16:19.000000Z
字数 1963
阅读 1413
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, request
app = Flask(__name__)
@app.before_request
def before_request():
print 'before request started'
print request.url
@app.before_request
def before_request2():
print 'before request started 2'
print request.url
g.name="SampleApp"
@app.after_request
def after_request(response):
print 'after request finished'
print request.url
response.headers['key'] = 'value'
return response
@app.teardown_request
def teardown_request(exception):
print 'teardown request'
print request.url
@app.route('/')
def index():
return 'Hello, %s!' % g.name
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
我们在全局定义了一个”index_called”信号对象,表示根路径被访问了。然后我们在根路径的请求处理中发出这个信号:
from blinker import Namespace
signals = 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)