Python Web框架Flask信号机制(signals)介绍

2019-10-05 11:37:49丽君

        recorded.append((template, context))
    template_rendered.connect(record, app)
    try:
        yield recorded
    finally:
        template_rendered.disconnect(record, app)


现在可以轻松地与测试客户端配对:



with captured_templates(app) as templates:
    rv = app.test_client().get('/')
    assert rv.status_code == 200
    assert len(templates) == 1
    template, context = templates[0]
    assert template.name == 'index.html'
    assert len(context['items']) == 10


确保订阅使用了一个额外的 **extra 参数,这样当 Flask 对信号引入新参数时你的调用不会失败。

代码中,从 with 块的应用 app 中流出的渲染的所有模板现在会被记录到templates 变量。无论何时模板被渲染,模板对象的上下文中添加上它。

此外,也有一个方便的助手方法(connected_to()) ,它允许你临时地用它自己的上下文管理器把函数订阅到信号。因为上下文管理器的返回值不能按那种方法给定,则需要把列表作为参数传入:



from flask import template_rendered

def captured_templates(app, recorded, **extra):
    def record(sender, template, context):
        recorded.append((template, context))
    return template_rendered.connected_to(record, app)


上面的例子看起来像这样:



templates = []
with captured_templates(app, templates, **extra):
    ...
    template, context = templates[0]

发送信号

如果你想要发送信号,你可以通过调用 send() 方法来达到目的。它接受一个发件者作为第一个参数和一些可选的被转发到信号用户的关键字参数:



class Model(object):
    ...

    def save(self):
        model_saved.send(self)


永远尝试选择一个合适的发送者。如果你有一个发出信号的类,把 self 作为发送者。如果你从一个随机的函数发出信号,把current_app._get_current_object()作为发送者。

基于信号订阅的装饰器

在Blinker 1.1中通过使用新的connect_via()装饰器你也能够轻易地订阅信号:

from flask import template_rendered

@template_rendered.connect_via(app)
def when_template_rendered(sender, template, context, **extra):
    print 'Template %s is rendered with %s' % (template.name, context)