Flask信号机制
信号是 Flask 中一项非常强大的功能。从软件工程角度讲,可以让数据传递代码彼此解耦;从功能实现角度讲,可以在某个事件发生时,就自动执行一系列的配套操作。下面分别讲解自定义信号和 Flask 内置信号。
自定义信号
Flask 从 0.6 版本开始就支持信号机制。信号的作用是在发生某个事情时,直接通知某个函数执行,可以达到代码间解耦的作用。Flask 中的信号是通过第三方库 blinker 实现的。我们先来学习一下如何创建信号以及发送信号,创建信号的示例代码如下。
from blinker import Namespace
# 定义Namespace对象
my_signals = Namespace()
# 创建名称为model-saved的信号
model_saved = my_signals.signal('model-saved')
上述代码中,首先是创建了一个 Namespace 对象 my_signals,然后通过 my_signals.signal 方法添加了一个名称为 model-saved 的信号。接着还需要订阅此信号,也就是在发生此信号时,需要执行什么代码,示例代码如下。
def log_model_saved(sender):
print("捕获到信号,发送者为:{}".format(sender))
my_signals.connect(log_model_saved)
上述代码中,首先通过 my_signals.connect 方法订阅信号,在信号产生后,会执行 log_model_saved 方法。然后在其他代码中如有需要的情况,就可以通过 my_signals.send 来发送信号了,示例代码如下。
class Model(object):
...
def save(self):
model_saved.send(self)
上述代码中,model_save.send 方法中的第 1 个参数是发送者,在订阅的函数中可以通过 sender 参数获取发送者的信息。
Flask内置信号
flask 中已经提前内置了许多信号,在相应的事件发生后,会发送信号,我们只需监听即可。在监听的时候,可以设置只接收哪个发送者发送的信号,一般设置为 app。下面来介绍常用的信号。
flask.template_rendered
模板渲染完毕后会发送此信号,示例代码如下。
from flask import template_rendered
def log_template_renders(sender, template, context, *args):
print('sender:', sender)
print('template:', template)
print('context:', context)
template_rendered.connect(log_template_renders, app)
flask.request_started
在接收到请求且到达视图函数之前会发送此信号,示例代码如下。
def log_request_started(sender, **extra):
print('sender:', sender)
print('extra:', extra)
request_started.connect(log_request_started, app)
flask.request_finished
请求结束后,在响应发送到客户端之前会发送此信号,示例代码如下。
def log_request_finished(sender, response, *args):
print('response:', response)
request_finished.connect(log_request_finished, app)