https://docs.djangoproject.com/zh-hans/3.2/topics/signals/
https://docs.djangoproject.com/zh-hans/3.2/ref/signals/
https://docs.djangoproject.com/zh-hans/4.0/topics/signals/
信号:signal
信号调度器:signal dispatcher
发送器:
接收器:
接收器函数:
发送信号时会调用接收器。信号的所有接收器函数都按照注册时的顺序一个接一个调用。
:::info
我的代码该放在哪?
严格来说,信号处理和注册的代码可以放在任何你喜欢的地方,但是推荐避免放在应用程序的根目录和 models 模块内以尽量减少导入代码的副作用。
在实践中,信号处理程序通常定义在与之相关的应用程序的 signals 子模块中。信号接收器在你应用程序配置类的 ready() 方法中连接。如果你使用 receiver() 装饰器,在 ready() 中导入 signals 子模块。 :::
连接接收器函数和信号
方法一:
from django.db import modelsfrom django.db.models.signals import post_saveclass Site(models.Model):"""Site模型类"""passdef my_callback(sender, **kwargs):"""信号接收器函数"""passpre_save.connect(my_callback, sender=Site)
方法二:
from django.db.models.signals import post_savefrom django.dispatch import receiverfrom django.db import modelsclass Site(models.Model):"""Site模型类"""pass@receiver(post_save)def my_callback(Site, **kwargs):"""信号接收器函数""""pass
from django.db.models.signals import post_savefrom django.dispatch import receiver
好处:降低耦合度
models.py
from django.db import modelsfrom django.db.models.signals import post_savefrom django.dispatch import receiverclass Node(models.Model):"""节点 模型类"""ENV_TYPE = (('0', '生产环境'),('1', '预生产环境'),('2', '测试环境'),)node_name = models.CharField(max_length=36, verbose_name='节点名称')dev_env_type = models.CharField(max_length=1, choices=ENV_TYPE, verbose_name='开发环境的类型')def __str__(self):return f'{self.node_name}'class NodeExtension(models.Model):"""节点的扩展信息 模型类"""node = models.OneToOneField(to='Node', verbose_name='关联的节点',on_delete=models.CASCADE, related_name='extension')remarks = models.TextField(verbose_name='描述性息')def __str__(self):return f'{self.node.node_name}'@receiver(post_save, sender=Node)def create_node_extension(sender, instance, created, **kwargs):"""信号处理函数:当存储Node类型的对象时,自动创建并存储NodeExtension对象"""if created:NodeExtension.objects.create(node=instance)else:instance.extension.save()

