【Django杂记】 Django Signals信号的使用

1、信号有哪些
  • Model_Signals
    • pre_init:Django中的model对象执行其构造方法前,自动触发
    • post_init:Django中的model对象执行其构造方法后,自动触发
    • pre_save:Django中的model对象保存前,自动触发
    • post_save:Django中的model对象保存后,自动触发
    • pre_delete:Django中的model对象删除前,自动触发
    • post_delete:Django中的model对象删除后,自动触发
    • m2m_changed:Django中的model对象使用m2m字段操作数据库的第三张表(add,remove,clear,update),自动触发
    • class_prepared:程序启动时,检测到已注册的model类,对于每一个类,自动触发
  • Managemeng_sinals
    • pre_migrate:执行migrate命令前,自动触发
    • post_migrate:执行migrate命令后,自动触发
  • Request/Response_signals
    • request_started:请求到来前,自动触发
    • request_finished:请求结束后,自动触发
    • got_request_exception:请求异常时,自动触发
  • Test_signals
    • setting_changed:配置文件改变时,自动触发
    • template_rendered:模型执行渲染操作时,自动触发
  • Database_Wrapperd
    • connection_created:创建数据库连接时,自动触发

2、内置信号如何使用呢?

  • 场景:
    • 有如下场景,我有一个Model名为Alert,表示一条告警,我需要在创建一个告警后进行邮件通知,怎么实现呢?
  • 常规实现:
    • Alert类加一个表示字段is_notify表示是否通过过,然后创建一个command,在后台定时读取Alert里未通知的记录:
for alert in Alert.objects.filter(is_notify = False):
    # 发邮件
    alert.is_notify = True
  • 缺点:
    • 需要创建一个后台进程
    • 需要增加一个字段标识是否通过
    • 后台进程的维护,如挂掉了,那么邮件通知不就终止了...
  • 使用信号呢?
@receiver(post_save, sender=Alert)
def alert_notify(sender, instance, created, **kwargs):
    if created:
        # 发送邮件
    return
  • 使用的方法:
    • 1、在自己的应用app下的init.py文件中:[假设我有一个名为tongjiapp的应用]
default_app_config = "tongjiapp.apps.TongjiappConfig"
    • 2、在自己应用的app下的apps.py文件中:
from django.apps import AppConfig

class TongjiappConfig(Appconfig):
    name = "tongjiapp"
    
    def ready(self):
        # 导入信号py文件
        import tongjiapp.signals.async_script_signals
    • 3、在async_script_sinals中代码如下:
from django.db.models.signals import post_migrate
from django.dispatch import receiver

@receiver(post_migrate)
def init_script(sender, **keargs):
    print("我执行了")
    # 操作

3、信号参数

  • pre_init
    • django.db.models.signals.pre_init
    • 每当你实例化Django模型时,该信号都会在模型的__init__()方法的开头发送
    • 参数:
      • sender:刚创建了一个实例的模型类
      • args:传递给__init__()的位置参数列表
      • kwargs:传递给__init__()的关键字参数的字典
  • pre_save
    • django.db.models.signals.pre_save
    • 这是在模型的save()方法的开头发送的
    • 参数:
      • sender:模型类
      • instance:正在保存的实际实例
      • raw:一个布尔值True,如果模型按照显示的方式保存(即当加载固定装置时);不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态。
      • using:正在使用的数据库别名
      • update_fields:如果有字段被传递给Model.save()方法,那么就是所传递的字段集,否则就是None
  • post_save
    • django.db.models.signals.post_save
    • 像pre_save一样,但是在save()方法的末尾发送
    • 参数:
      • sender:模型类
      • instance:正在保存的实际实例
      • created:一个布尔值,True如果创建新记录
      • raw:一个布尔值True,如果模型按照显示的方式保存(即当加载固定装置时);不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态
      • using:正在使用的数据库别名
      • update_fields:如果有字段被传递给Model.save()方法,那么就是所传递的字段集,否则就是None
  • pre_delete
    • django.db.models.signals.pre_delete
    • 在模型的delete()方法和queryset的delete()方法的开头发送
    • 参数:
      • sender:模型类
      • instance:正在删除的实际实例
      • using:正在使用的数据库别名
  • post_delete
    • django.db.models.signals.post_delete
    • 像pre_delete一样,但是在模型的delete()方法和queryset的delete()方法的末尾发送
    • 参数:
      • sender:模型类
      • instance:正在删除的实际实例
        • 注意:该对象将不再位于数据库中,所以要非常小心使用此实例
      • using:正在使用的数据库别名
  • m2m_changed
    • django.db.models.signals.m2m_changed
    • 在模型实例上更改了ManyToManyField时发送。严格来说,这不是一个模型信号,因为它是由ManyToManyField发送的,但由于它补充了pre_save/post_save和pre_delete/post_delete当跟踪模型更改时,它包括在这里。
    • 参数:
      • sender:描述ManyToManyField的中间模型类。 当定义多对多字段时,此类自动创建;您可以使用多对多字段上的through属性访问它。
      • instance:多对多关系更新的实例。 这可以是sender或ManyToManyField相关的类的一个实例。
      • action:指示在关系上完成的更新类型的字符串。 这可以是以下之一
        • pre_add:在之前发送一个或多个对象被添加到关系中。
        • post_add:在之后发送一个或多个对象被添加到关系中。
        • pre_remove:在之前发送一个或多个对象从关系中删除。
        • post_remove:在之后发送一个或多个对象从关系中删除。
        • pre_clear:在之前发送关系被清除。
        • post_clear:之后发送关系被清除。
        • reverse:指示关系的哪一侧被更新(即,如果它是正在被修改的正向或反向关系)。
        • model:从关系中删除或从关系中清除的对象的类。
        • pk_set:对于pre_add,post_add,pre_remove和post_remove操作,这是一组主键值加入或从关系中删除。
        • 对于pre_clear和post_clear操作,这是None。
      • using:正在使用的数据库别名
  • class_prepared
    • django.db.models.signals.class_prepared
    • 每当模型类"准备"时发送,即一旦模型已经被定义并在Django的模型系统中注册。Django内部使用这个信号;它通常不会用于第三方应用程序。
    • 由于此信号是在应用程序注册表群集进程期间发送的,并且在应用注册表完全填充后运行AppConfig.ready(),因此无法使用该方法连接接收器。一种可能性是连接他们AppConfig.__init__(),注意不要导入模型或触发对应用程序注册表的调用
    • 参数:
      • send:ready的model类
管理信号:
  • pre_migrate
    • django.db.models.signals.pre_migrate
    • 在开始安装应用程序之前,有migrate命令发送。对于缺少models模块的应用,不会发送。
    • 参数:
      • sender:应用程序即将迁移/同步的AppConfig实例
      • APP_CONFIG:与sender相同
      • verbosity:指示manage.py在屏幕上打印多少信息。有关详细信息,请参阅--verbosity标志。监听pre_migrate的函数应根据该参数的值调整输出到屏幕的内容
      • interactive:如果interactive是True,则可以安全地提示用户在命令行中输入内容。如果interactive为False,则侦听此信号的功能不应尝试提示任何内容。
        • 例如:当interactive为True时,django.contrib.auth应用程序仅提示创建超级用户
      • using:命令将在其上运行的数据库的别名
      • plan:迁移计划将用于迁移运行,虽然该计划不是公共API,但这在允许罕见的情况下需要知道计划。一个计划是两个元组的列表,第一个项目时迁移类的实例,第二个项目显示迁移是否回滚(True)或应用(False)
      • apps:django中的新功能1.10。包含迁移运行前的项目状态的Apps的实例。应该使用它来代替全局apps注册表来检索要执行操作的模型。
  • post_migrate
    • django.db.models.signals.post_migrate
    • 在migrate(即使不进行迁移)和flush命令的末尾发送。对于缺少models模块的应用,不会发送。
    • 注意:此信号的处理程序不得执行数据库模式更改,因为如果在migrate命令期间运行,则可能会导致flush命令失败。
    • 参数:
      • sender:刚刚安装的应用程序的AppConfig实例
      • APP_CONFIG:与sender相同
      • verbosity:指示manage.py在屏幕上打印多少信息。有关详细信息,请参阅--verbosity标志。监听post_migrate的函数应根据该参数的值调整输出到屏幕的内容
      • interactive:如果interactive是True,则可以安全地提示用户在命令行中输入内容。如果interactive为False,则侦听此信号的功能不应尝试提示任何内容。
        • 例如:当interactive为True时,django.contrib.auth应用程序仅提示创建超级用户
      • using:用于同步的数据库别名。默认为default数据库
      • plan:迁移计划将用于迁移运行,虽然该计划不是公共API,但这在允许罕见的情况下需要知道计划。一个计划是两个元组的列表,第一个项目时迁移类的实例,第二个项目显示迁移是否回滚(True)或应用(False)
      • apps:django中的新功能1.10。包含迁移运行前的项目状态的Apps的实例。应该使用它来代替全局apps注册表来检索要执行操作的模型。
请求/响应信号
  • 处理请求时由核心框架发送的信号
  • request_started
    • django.core.signals.request_started
    • 当Django开始处理http请求时发送
    • 参数:
      • sender:处理程序类;例如django.core.handlers.wsgi.WsgiHandler:处理该请求
      • ENVIRON:environ字典提供给请求
  • request_finished
    • django.core.signals.request_finished
    • 当Django完成向客户端传递HTTP响应时发送
    • 参数:
      • sender:处理程序类,如上。
  • got_request_exception
    • django.core.signals.got_request_exception
    • 当Django在处理传入的HTTP请求时遇到异常时,会发送此信号
    • 参数:
      • sender:处理程序类,如上。
      • request:HttpRequest对象
测试信号
  • 信号只在runing tests时发送
  • setting_changed
    • django.test.signals.setting_changed
    • 当通过django.test.TestCase.settings()上下文管理器或django.test.override_settings()装饰器/上下文管理器
    • 实际发送两次:应用新值("setup")和恢复原始值("拆除")时。使用enter参数来区分两者。你还可以从django.core.signals导入此信号,以避免在非测试情况下从django.test导入。
    • 参数:
      • sender:设置处理程序
      • setting:设置的名称
      • value:更改后的设置值。对于最初不存在的设置,在"拆除"阶段,value为None
      • enter:一个布尔值,True如果应用设置,False如果还原
  • template_rendered
    • django.test.signals.template_rendered
    • 测试系统呈现模板时发送。在Django服务器的正常操作期间不发出此信号,它仅在测试期间可用。
    • 参数:
      • sender:被渲染的Template对象
      • template:与发信人相同
      • context:模板呈现的Context
数据库包装器
  • 当数据库连接启动时,由数据库包装器发送的信号。
  • connection_created
    • django.db.backends.signals.connection_created
    • 当数据库包装器与数据库进行初始连接时发送。如果你想将任何后续连接命令发送到SQL后端,这一点尤其有用。
    • 参数:
      • sender:数据库包装器类:即django.db.backends.postgresql.DatabaseWrapper或django.db.backends.mysql.DatabaseWrapper等
      • connection:打开的数据库连接。这可以在多数据库配置中使用,以区分来自不同数据库的连接信号。

posted @ 2022-05-31 13:42  郭祺迦  阅读(355)  评论(0编辑  收藏  举报