Django信号的基本使用

Django信号的基本使用

介绍

信号在 Django 中的作用是允许开发者在特定事件发生时执行自定义逻辑。通过连接信号到相应的处理函数,开发者可以轻松地在应用程序的不同部分添加额外的处理逻辑,而无需修改原始的代码

信号的作用包括但不限于:

  1. 解耦合:使用信号可以将特定功能的实现从原始的业务逻辑中解耦出来,提高了代码的模块化程度,降低了代码的耦合性
  2. 扩展性:允许第三方应用或插件通过连接信号的方式来扩展应用程序的功能,而无需修改应用程序的源代码
  3. 事件驱动:使得应用程序变得事件驱动,即当特定事件发生时,可以触发相关的处理逻辑,增强了应用程序的灵活性
  4. 可重用性:通过连接信号,可以编写通用的信号处理函数,使得这些处理逻辑能够被多个事件重用,提高了代码的可重用性

常用内置信号

信号类别信号名称触发时机发送者参数
模型层信号pre_save模型实例保存前模型的classsender(模型类)、instance(模型实例)、raw(是否为原始查询)、using(使用的数据库别名)、update_fields(仅当更新特定字段时提供)
post_save模型实例保存后模型的class同上,另加created(是否是新创建的实例)
pre_delete模型实例删除前模型的classsender(模型类)、instance(模型实例)、using(使用的数据库别名)
post_delete模型实例删除后模型的class同上
m2m_changed多对多关系变更时模型的classsender(模型类)、action(操作类型,如"add", "remove", "clear")、reverse(是否为反向关系)、model(关联模型)、pk_set(变更的PK集合,对于"add""remove")、instance(触发变更的实例)
pre_init模型实例初始化前模型的classsender(模型类)、args(传递给__init__方法的参数)、kwargs(传递给__init__方法的关键字参数)
post_init模型实例初始化后模型的class同上
管理信号pre_migrate在执行migrate命令前Django内部信号系统无特定参数,但可能包含Django内部使用的信息
post_migrate在执行migrate命令后Django内部信号系统sender:当前正在处理的应用配置(AppConfig)的实例 、app_config:同上(在旧版Django中可能是app)、verbosity:命令行输出信息的详细级别(通常是整数) ,interactive:是否是交互式运行(例如,在shell中,而不是通过脚本)、using:用于迁移的数据库别名(默认是default)、 apps:一个包含所有已加载应用的字典
请求/响应信号request_started在请求到来前Django内部信号系统无特定参数,但可能包含与请求相关的内部信息
request_finished在请求结束后Django内部信号系统senderNone(通常不使用) 、request:当前请求的HttpRequest对象
got_request_exception在请求异常后Django内部信号系统senderNone(通常不使用) 、request:当前请求的HttpRequest对象、 exception:在请求处理过程中引发的异常对象
测试信号setting_changed在使用test测试修改配置文件时django.test.signals.setting_changedsenderdjango.conf.Settings的实例、 setting:发生更改的设置的名称(字符串)、 value:设置的新值、 enter:布尔值,表示是否正在进入上下文(例如,使用override_settings装饰器时)
template_rendered在使用test测试渲染模板时django.test.signals.template_renderedsenderdjango.template.backends.base.Template的实例 、template:用于渲染的模板对象 、context:模板渲染时使用的Context对象
数据库信号connection_created在创建数据库连接时数据库后端(如django.db.backends.postgresql.base.DatabaseWrappersender:数据库连接的实例(例如,PostgreSQL后端的DatabaseWrapper

使用演示

假设现在有一个User表,需求:在User实例被创建时(添加用户后)控制台打印该用户邮箱

1.创建用户表

AbstractUser继承,这是 Django 内置的代表用户的模型,用户名就是username不需要我们重写,额外扩写了email字段

import json

from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    email = models.EmailField(verbose_name='邮箱', help_text='邮箱', null=True, blank=True)


    class Meta:
        db_table = 'user'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

2.创建信号接收器(接受函数)

在需要使用信号的app文件下新建signals.py,并新建信号接收函数my_handler

  • sender:模型类
  • instance:模型实例
  • created:是否是新建的实例
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User


@receiver(post_save, sender=User)
def my_handler(sender, instance, created, **kwargs):
    if created:
        print(f"用户{instance.username}已经被创建, 邮箱{instance.email}:, model来源:{sender.__name__}")
    else:
        print(f"{instance.username} 已更新新邮箱: {instance.email}")

3.将信号添加至应用配置

在 Django 启动时,会执行 ready() 方法,并且会导入并注册用户信号处理函数模块。

# apps.py
from django.apps import AppConfig


class UserConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'user'

    def ready(self):
        import user.signals  # 在这里导入信号处理函数模块,user是app的名称

4.测试

对接口进行添加用户操作

{
    "username":"tianqing",
    "password":"2e2e2e2e2e",
    "email":"azure@qq.com",
}

控制台输出:

image-20240623183245120

现在对用户进行更新

{
    "username":"tianqing",
    "password":"2e2e2e2e2e",
    "email":"azure1@qq.com",
}

控制台输出:

image-20240623183604353

自定义信号

其实自定义信号只比内置信号多了两步:定义信号,.send发送信号

定义信号一般也在signals.py中执行

在任何想要使用信号的地方直接.send发送信号

1.定义信号

# myapp/signals.py  
from django.dispatch import Signal  
  
# 定义一个名为 my_custom_signal 的信号,允许的参数sender和message
my_custom_signal = Signal(providing_args=["sender", "message"])

2.发送信号

# myapp/views.py  
from .signals import my_custom_signal  
  
def some_view(request):  
    # ... 执行一些操作 ...  
      
    # 发送信号,带上 sender 和 message 参数  
    my_custom_signal.send(sender=self.__class__, message="这是一条自定义信号")  
      
    # ... 其他操作 ...

3.创建信号接收器

# myapp/signals.py  
from django.dispatch import receiver  
from .models import MyModel  
  
@receiver(my_custom_signal)  
def my_signal_receiver(sender, **kwargs):  
    message = kwargs.get('message')  
    print(f"信号来源:{sender}: {message}")  
  
    # 你也可以在这里进行其他操作,比如保存到数据库、发送邮件等  
    # 例如,你可以创建一个 MyModel 的实例来保存信号的信息  
    MyModel.objects.create(content=message)

4.将信号添加至应用配置

# myapp/apps.py  
from django.apps import AppConfig  
  
class MyAppConfig(AppConfig):  
    name = 'myapp'  
  
    def ready(self):  
        import myapp.signals  # 导入 signals 模块,以触发信号接收函数的连接
  • 38
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值