Fork me on GitHub

Flask学习笔记(十八)-Flask 信号机制

一、说明

官方文档 - 信号参考

Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为

安装:pip3 install blinker

二、自定义信号

自定义信号:自定义信号分为3步,第一是定义一个信号,第二是监听一个信号,第三是发送一个信号

  • 定义信号:定义信号需要使用到blinker这个包的Namespace类来创建一个命名空间。比如定义一个在访问了某个视图函数的时候的信号。示例代码如下:

      from blinker import Namespace
    
      mysignal = Namespace()
      visit_signal = mysignal.signal('visit-signal')
    
  • 监听信号:监听信号使用singal对象的connect方法,在这个方法中需要传递一个函数,用来接收以后监听到这个信号该做的事情。示例代码如下:

  def visit_func(sender,username):
    print(sender)
    print(username)

  mysignal.connect(visit_func)
  • 发送信号:发送信号使用singal对象的send方法,这个方法可以传递一些其他参数过去。示例代码如下:
  mysignal.send(username='zhiliao')

实例展示:

signals.py
from blinker import Namespace
from  datetime import datetime
from flask import request,g
#1、定义信号
namespace=Namespace()
login_signal=namespace.signal('login1')

#2、监听信号
def login_log(sender):
    #用户名,登录的时间,ip地址
    now=datetime.now()
    ip=request.remote_addr
    log_line=f"{g.username}*{now}*{ip}"
    with open('login_log.txt','a') as fp:
        fp.write(log_line+"\n")
        print('用户登录了')
#连接信号
login_signal.connect(login_log)
signal_demo.py
from flask import Flask,request,g
from  signals import login_signal
app=Flask(__name__)
@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/login')
def login():
    #通过查询字符串的形式来传递username这个参数
    username=request.args.get('username')
    if username:
        g.username=username
        login_signal.send()
        return "登录成功"
    else:
        return "请输入用户名"


if __name__ == '__main__':
    app.run(debug=True)

运行结果:

 

 

三、内置信号参数

request_started = _signals.signal('request-started') # 请求到来前执行
request_finished = _signals.signal('request-finished') # 请求结束后执行
before_render_template = _signals.signal('before-render-template') # 模板渲染前执行
template_rendered = _signals.signal('template-rendered') # 模板渲染后执行
got_request_exception = _signals.signal('got-request-exception') # 请求执行出现异常时执行
request_tearing_down = _signals.signal('request-tearing-down') # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
appcontext_pushed = _signals.signal('appcontext-pushed') # 应用上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped') # 应用上下文pop时执行
message_flashed = _signals.signal('message-flashed') # 调用flask在其中添加数据时,自动触发  

举例:got_request_exception 

signal_demo.py
from flask import Flask,request,g,render_template,got_request_exception
from  signals import login_signal

app=Flask(__name__)

#请求执行出现异常时执行
def request_exception_log(sender,exception):
    print(exception)
    with open('login_log.txt', 'a') as fp:
        fp.write("打印请求异常信息:"+str(exception) + "\n")
got_request_exception.connect(request_exception_log)

@app.route('/')
def hello_world():
    a=1/0
    return render_template('index.html')

@app.route('/login')
def login():
    #通过查询字符串的形式来传递username这个参数
    username=request.args.get('username')
    if username:
        g.username=username
        login_signal.send()
        return "登录成功"
    else:
        return "请输入用户名"


if __name__ == '__main__':
    app.run(debug=True)

执行结果:

 

 

其他内置信号操作类似-可自行百度  

posted @ 2022-11-03 23:30  橘子偏爱橙子  阅读(85)  评论(0编辑  收藏  举报