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 models
from django.db.models.signals import post_save
class Site(models.Model):
"""Site模型类"""
pass
def my_callback(sender, **kwargs):
"""信号接收器函数"""
pass
pre_save.connect(my_callback, sender=Site)
方法二:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import models
class Site(models.Model):
"""Site模型类"""
pass
@receiver(post_save)
def my_callback(Site, **kwargs):
"""信号接收器函数""""
pass
from django.db.models.signals import post_save
from django.dispatch import receiver
好处:降低耦合度
models.py
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class 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()