首页 > 其他分享 >django中的信号机制

django中的信号机制

时间:2024-06-22 13:10:02浏览次数:11  
标签:sender django 信号 receiver import 机制 save post

django中的信号机制

1.1 什么是信号机制

# 什么是信号机制
Django 框架包含了一个信号机制,它允许若干个发送者(sender)通知一组接收者(receiver)某些特定操作或事件(events)已经发生了, 接收者收到指令信号(signals)后再去执行特定的操作。

1.2 信号的工作机制

Django 中的信号工作机制依赖如下三个主要要素:

# 1.发送者(sender)
信号的发出方,可以是模型,也可以是视图。当某个操作发生时,发送者会发出信号。

# 2.信号(signal)
发送的信号本身。Django内置了许多信号,比如模型保存后发出的post_save信号。

# 3.接收者(receiver)
信号的接收者,其本质是一个简单的回调函数。将这个函数注册到信号上,当特定的事件发生时,发送者发送信号,回调函数就会被执行。

1.3 信号的应用场景

信号主要用于Django项目内不同事件的联动,实现程序的解耦。比如当模型A有变动时,模型B与模型C收到发出的信号后同步更新。又或当一个数据表数据有所改变时,监听这个信号的函数可以及时清除已失效的缓存。另外通知也是一个信号常用的场景,比如有人刚刚回复了你的贴子,可以通过信号进行推送。

注意:Django中信号监听函数不是异步执行,而是同步执行,所以需要异步执行耗时的任务时(比如发送邮件或写入文件),不建议使用Django自带的信号。

1.4 简单例子

1.4.1

'''
假如我们有一个Profile模型,与User模型是一对一的关系。我们希望创建User对象实例时自动创建Profile对象实例,而更新User对象实例时不创建新的Profile对象实例。这时我们就可以自定义 create_user_profile和save_user_profile两个监听函数,同时监听sender (User模型)发出的post_save信号。由于post_save可同时用于模型的创建和更新,我们用if created这个判断来加以区别。
'''

from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
 
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    birth_date = models.DateField(null=True, blank=True)

# 监听User模型创建    
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
   if created:
       Profile.objects.create(user=instance)

# 监听User模型更新  
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

1.4.2

'''
我们再来看一个使用信号清除缓存的例子。当模型A被更新或被删除时,会分别发出post_save和post_delete的信号,监听这两个信号的receivers函数会自动清除缓存里的A对象列表。
'''

from django.core.cache import cache
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver

@receiver(post_save, sender=ModelA)
def cache_post_save_handler(sender, **kwargs):
    cache.delete('cached_a_objects')
    
@receiver(post_delete, sender=ModelA)
def cache_post_delete_handler(sender, **kwargs):
     cache.delete('cached_a_objects')
        

# 注意:有时为了防止信号多次发送,可以通过dispatch_uid给receiver函数提供唯一标识符。
@receiver(post_delete, sender=ModelA, dispatch_uid = "unique_identifier")

Django常用内置信号

pre_save & post_save: 在模型调用 save()方法之前或之后发送。

pre_init& post_init: 在模型调用_init_方法之前或之后发送。

pre_delete & post_delete: 在模型调用delete()方法或查询集调用delete() 方法之前或之后发送。

m2m_changed: 在模型多对多关系改变后发送。

request_started & request_finished: Django建立或关闭HTTP 请求时发送。

'''
注意:监听pre_save和post_save信号的回调函数不能再调用save()方法,否则回出现死循环。另外Django的update方法不会发出pre_save和post_save的信号。
'''

如何放置信号监听函数代码

'''
在之前案例中,我们将Django信号的监听函数写在了models.py文件里。当一个app的与信号相关的自定义监听函数很多时,此时models.py代码将变得非常臃肿。一个更好的方式把所以自定义的信号监听函数集中放在app对应文件夹下的signals.py文件里,便于后期集中维护。
'''


# 1.假如我们有个account的app,包含了User和Profile模型,我们首先需要在account文件夹下新建signals.py,如下所示:

# account/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, Profile

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
  if created:
      Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()
    
    
    
# 2.接下来我们需要修改account文件下apps.py和__init__.py,以导入创建的信号监听函数。

# apps.py
from django.apps import AppConfig
 
class AccountConfig(AppConfig):
    name = 'account'
 
    def ready(self):
        import account.signals
        
# account/__init__.py中增加如下代码:
default_app_config = 'account.apps.AccountConfig'

自定义信号

# 1.自定义信号
'''
每个自定义的信号,都是Signal类的实例。这里我们首先在app目录下新建一个signals.py文件,创建一个名为my_signal的信号,它包含有msg这个参数,这个参数在信号触发的时候需要传递。当监听函数收到这个信号时,会得到msg参数的值。
'''
from django.dispatch import Signal

my_signal = Signal(providing_args=['msg'])



# 2.触发信号
'''
视图中进行某个操作时可以使用send方法触发自定义的信号,并设定msg的值。
'''
from . import signals

def index(request):
    signals.my_signal.send(sender=None, msg='Hello world')
    return render(request, template_name='index.html')

# 3.将监听函数与信号相关联
'''
这样每当用户访问/index/视图时,Django都会发出my_signal的信号(包含msg这个参数)。回调函数收到这个信号后就会打印出msg的值来。
'''

from django.dispatch import Signal, Receiver

my_signal = Signal(providing_args=['msg'])

@receiver(my_signal)
def my_signal_callback(sender, **kwargs):
    print(kwargs['msg']) # 打印Hello world!

标签:sender,django,信号,receiver,import,机制,save,post
From: https://www.cnblogs.com/Hqqqq/p/18262177

相关文章

  • 【YOLOv10改进实战】**【6】YOLOv10添加注意力机制 【手把手教学】【经典模块随心选】
    【YOLOv10改进实战】**【6】YOLOv10添加【CBAM】【SE】【CA】【ECA】注意力机制【手把手教学】【经典模块随心选】......
  • 基于时间卷积门控循环单元融合注意力机制TCN-GRU-Attention实现负荷多变量时间序列预
    %导入数据load(‘data.mat’);%请替换为你的数据文件名%数据应该是一个矩阵,每一行代表一个时间步,每一列代表一个特征或变量%划分训练集和测试集trainRatio=0.8;%训练集比例trainSize=round(trainRatio*size(data,1));trainData=data(1:trainSize,......
  • Spring Boot 源码分析五:Spring Boot AutoConfiguration 自动配置机制
    1.引言在前几篇文章中,我们探讨了SpringBoot的启动流程及其扩展机制。在本篇文章中,我们将深入分析SpringBoot的自动配置(AutoConfiguration)机制,这是SpringBoot最具特色和强大的功能之一。2.自动配置概述SpringBoot的自动配置机制旨在根据项目中的类路径和配置属性,自......
  • 详解 ClickHouse 的副本机制
    一、简介副本功能只支持MergeTreeFamily的表引擎,参考文档:https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/replication/ClickHouse副本的目的主要是保障数据的高可用性,即使一台ClickHouse节点宕机,那么也可以从其他服务器获得相同的数据......
  • 探索信号世界的奥秘:MATLAB中的傅里叶变换、滤波器与FFT仿真设计
    探索信号世界的奥秘:MATLAB中的傅里叶变换、滤波器与FFT仿真设计一、引言:信息技术的脉搏——信号处理二、技术概述:理论与实践的桥梁傅里叶变换滤波器设计FFT(快速傅里叶变换)代码示例:基本FFT应用三、技术细节:深入理解背后的数学原理傅里叶变换原理滤波器设计原理FFT算法解......
  • 一对一聊天源码,你是否了解ERedis的扩容机制?
    一对一聊天源码,你是否了解ERedis的扩容机制?Redis的扩容时机Redis会在如下两种情况触发扩容。1、如果没有fork子进程在执行RDB或者AOF的持久化,一旦满足ht[0].used>=ht[0].size,此时触发扩容;2、如果有fork子进程在执行RDB或者AOF的持久化时,则需要满足ht[0].used>5*ht......
  • Django REST framework安全实践:轻松实现认证、权限与限流功能
    系列文章目录Django入门全攻略:从零搭建你的第一个Web项目DjangoORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作DjangoORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解DjangoORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践跨域问题与Django解......
  • JVM类加载器与双亲委派机制
    通过上一篇Java的类加载机制相信大家已经搞明白了整个类加载从触发时机,接着我们就来看下类加载器,因为类加载机制是有加载器实现的。 类加载器的分类启动类加载器BootstrapClassLoader是Java虚拟机(JVM)的一部分,它负责加载Java核心库,也就是JavaRuntimeEnvironment......
  • 汽车功能安全(ISO 26262)系列_ 系统阶段开发 - 技术安全需求(TSR)及安全机制
    汽车功能安全(ISO 26262)系列: 系统阶段开发 - 技术安全需求(TSR)及安全机制01. 什么是TSR附赠自动驾驶最全的学习资料和量产经验:链接总体而言,技术安全需求(TSR: Technical Safety Requirement)是为满足安全目标SG或功能安全需求(FSR),由功能安全需求(FSR)在技......
  • Go 内存模型与分配机制
    ......