信号

信号

一 信号是什么

# 1 Flask框架中的信号基于blinker,其主要就是让开发者可以在flask请求过程中定制一些用户行为
# 2 信号是典型的 观察者模式
	-触发某个事执行【模板准备渲染】
    -绑定信号:可以绑定多个
    	只要模板准备渲染--》就会执行这几个绑定的新--》函数
        
        
# 3 面向切面编程(AOP)--》一种方案
	-整个程序正常运行,但是我们可以把一部分代码,插入到某个位置执行
    -钩子函数:只要写了,程序走到哪,就会执行,没写,就不会执行
    	-序列化类的校验
	
# 4 通过信号可以做什么事?
	-在框架整个执行过程中,插入一些代码执行
    	比如:记录某个页面的访问量
    	比如:每次渲染 login.html --->都记录日志
        比如:程序出异常---》记录日志
        比如:用户表中有个用户创建--》给这个用户发点短信
        比如:用户下了订单---》发个邮件通知,让它尽快付款
        
        比如:轮播图表只要发生变化,就删缓存:django中内置信号

二 flask中信号的使用

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在其中添加数据时,自动触发

1 内置信号的使用

使用步骤:

  1. 写一个函数

    def func1(*args,**kwargs):
        print('模板渲染了')
        print(args)
        print(kwargs.get('template').name)
    
  2. 跟内置信号绑定

    from flask import signals
    signals.before_render_template.connect(func1)
    
  3. 等待触发(自动)

2 自定义信号

使用步骤:

  1. 定义一个自定义信号

    from flask.signals import _signals
    create_user = _signals.signal('create_user')
    
  2. 写一个函数

    def func1(*args, **kwargs):
        print('自定义信号执行了')
        print(args)
        print(kwargs)
    
  3. 跟内置信号绑定

create_user.connect(func1)
  1. 等待触发(手动)

     create_user.send()
    

三 django中信号使用

Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发

1 内置信号使用

  1. 写一个函数

    def callBack(sender, **kwargs):
        # 过滤banner表   :kwargs就有表名
    	print('对象保存了')
    
  2. 跟内置信号绑定

    from django.db.models.signals import pre_save
    post_save.connect(callBack)
    
  3. 等待触发(自动的)

绑定方式二,使用装饰器

pre_save

from django.db.models.signals import pre_save
from django.dispatch import receiver
.models import MyModel
@receiver(pre_save, sender=MyModel)
def my_callback(sender, instance, **kwargs):
    print("对象创建成功")
    print(sender)
    print(kwargs)
    
# sender 是发送信号的模型,这里是 MyModel。
# instance 是即将保存的模型实例。
# **kwargs 接受其他关键字参数。

post_save

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import MyModel

@receiver(post_save, sender=MyModel, dispatch_uid="model_post_save")
def mymodel_post_save(sender, instance, created, **kwargs):
    if created:
        # 执行某些操作,例如发送通知或更新其他模型
        print(f"新建了一个 ApplyRedisText 实例: {instance}")
    else:
        # 执行某些操作,例如记录修改
        print(f"更新了一个 ApplyRedisText 实例: {instance}")


# sender 参数指明发送信号的模型,这里是 MyModel。
# instance 是被保存的模型实例。
# created 是一个布尔值,指示该实例是新创建的还是已经存在的实例被更新。
# **kwargs 接受其他关键字参数。

request_started

from django.core.signals import request_started
from django.dispatch import receiver

@receiver(request_started)
def my_request_started_handler(sender, environ, **kwargs):
    # 在请求开始时执行某些操作
    print("Request started!")
    # 你可以在这里添加更多逻辑,比如记录日志
    # logger.info(f"Request started from {environ['REMOTE_ADDR']}")

# sender 是发送信号的对象,一般是 WSGIHandler。
# environ 是 WSGI 环境字典,包含关于请求的信息。
# **kwargs 接受其他关键字参数。

# 可以将信号处理函数放在 signals.py 文件中,并在 apps.py 中的 ready 方法中导入它。
from django.apps import AppConfig

class MyappConfig(AppConfig):
    name = 'myapp'

    def ready(self):
        import myapp.signals  # 导入信号处理模块

2 自定义信号

# 1 定义信号(一般创建一个py文件)(toppings,size 是接受的参数)
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

#2  写个函数注册信号
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
pizza_done.connect(callback)

# 3 触发信号
from 路径 import pizza_done
pizza_done.send(sender='seven',toppings=123, size=456)

四 用信号的好处

代码侵入性低---》解耦

五 信号和信号量

# 信号:signal 
	-flask,django中得 观察者模式  --》信号机制
    
# 信号量:Semaphore
	-并发编程中概念
    在Python中,信号量(Semaphore)主要用来控制多个线程或进程对共享资源的访问。信号量本质上是一种计数器的锁,它维护一个许可(permit)数量,每次 acquire() 函数被调用时,如果还有剩余的许可,则减少一个,并允许执行;如果没有剩余许可,则阻塞当前线程直到其他线程释放信号量
posted @ 2024-06-24 08:56  蓝幻ﹺ  阅读(12)  评论(0编辑  收藏  举报