在Flask中,如何在blueprint中接受signals

hymanHu
  • 24

我使用flask_login管理登陆用户session,为了给登陆用户写日志,决定使用signals.代码如下:

    @user_logged_in.connect_via(app)
    def log_info(sender, user, **kw):
        print 'test in log info'
        current_app.behavior_logger.info(u'[login]%s login' % user.name)

然而该代码只能在有app变量的python文件中生效,在blueprint中无效。
我尝试app = current_app或者app = xx_blueprint均无效。

请问flask api文档中说的singals sender 是指什么,如何在blueprint中接受signal呢

回复
阅读 4k
1 个回答
✓ 已被采纳

Flask 文档中的那些 signals,它们的发送都是当前 flask app,因此,当你连接到 request_started 一类的 flask 框架级内置信号时,flask app 会向 receiver 发送信号。

此时的 sender 就是 app,就是那个 app = flask.Flask(__name__) 的 app 对象。 receiver,就是注册到信号接收者列表中的函数们。

注意:

  1. 对于内置信号,当你注册好了以后,app 启动了以后,flask 会在相应的场景下主动 send,而不需要你手动 send,比如 request_started,当请求开始时它就会发。

  2. 内置信号之外的,你得自己来控制何时 send。

  3. sender 必须是你 receiver 函数指定的同一对象。

回头来看题主的问题。

你的 @user_logged_in.connect_via(app) 将 app 设置为了 sender。

你改成 app = current_app 或者 app = xx_blueprint 肯定都是无效的,因为一来前面那个 current_app 并没有 send 什么出去,二来后面的 xx_blueprint 又不是 connect_via(app) 处的 app

so,如何在 blueprint 里接收信号呢?

  1. connect_via(app) 的第一个参数需要改为你的 blueprint 对象

  2. 在这个 blueprint 对象的相关上下文中 send 消息

比如:

my_signals = signals.Namespace()
signal_for_bp = my_signals.signal("bp")

bp_shajiquan = Blueprint("bp_shajiquan", __name__, url_prefix="/bp")

# 当信号通过 bp_shajiquan 连接时,也就是当 sender 为 bp_shajiquan 时
@signal_for_bp.connect_via(bp_shajiquan)
def log_bp_shajiquan(sender, *args, **kwargs):
    print("信号 sender 及内容:", sender, kwargs)
    assert(sender.name == "bp_shajiquan")

# bp_shajiquan 这个 blueprint 的每个请求前,都运行 before_every_request_in_bp 函数
@bp_shajiquan.before_request
def before_every_request_in_bp():

    # 向信号发送消息,赞美良辰,每个请求,都会赞美……
    signal_for_bp.send(bp_shajiquan, msg="你只需要记住,我叫叶良辰。每次请求,你都要记住!", name="良辰粉丝")

# 写个 view
@bp_shajiquan.route('/<string:username>')
def bp_shajiquan_user_profile(username):
    signal_for_bp.send(bp_shajiquan, name="叶良辰", msg="你若是感觉有实力跟我玩,良辰不介意奉陪到底....")

    # 这条就发不过去, 因为 sender 不匹配
    signal_for_bp.send(app, name="良辰黑", msg="这条就发不过去....")
    return "良辰找你很久了,亲爱的:  " + username
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏