Django的信号
信号是什么?
信号可以理解为Django内部的一种事件发布-订阅机制。某个事件被触发,则所有订阅和关注该事件的订阅都会接收到通知。
例如,当第三方应用关于Django应用配置发生改变的信号时:
def request_started_signal(sender, **kwargs):
print("Request started")
class CommentConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'comment'
def ready(self):
"""当应用启动时自动调用ready"""
from django.core.signals import request_started
request_started.connect(request_started_signal)
Django 的 内置信号 允许用户代码在某些操作发生时收到通知。
警告
信号看起来是松散耦合的表现,但它们很快会导致难以理解、调整和调试的代码。
在可能的情况下,你应该选择直接调用处理代码,而不是通过信号进行分发。
信号的订阅和接收
request_started.connect(request_started_signal)
可以将信号订阅到一个本地方法,在信号被触发时,自动调用该方法。
另外一种订阅方式是使用 receiver()
装饰器:
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
request_started_signal
函数接收一个 sender
参数以及关键字参数 (**kwargs
);所有信号处理程序都必须接受这些参数。
只订阅特定发送者的信号
仔细考虑 django.db.models.signals.pre_save
在模型保存之前发送的信号。假如你只想知道某个 特定 模型何时被保存。
from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel
@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs): ...
订阅时指定sender参数,可以将订阅限制在特定发送者信号。
防止重复订阅
from django.core.signals import request_finished
request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")
订阅时指定dispatch_uid参数,可以将订阅限制在一次中。
定义、触发和取消订阅
所有的信号都是 django.dispatch.Signal
的实例。
例如:
import django.dispatch
pizza_done = django.dispatch.Signal()
class PizzaStore:
...
def send_pizza(self, toppings, size):
pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
这声明了一个 pizza_done
信号,并使用send
触发信号。
要从信号中断开接收者,调用 Signal.disconnect()
。