Django 的 signal 听起来很神奇,但是它并不是什么复杂的东西。它看起来像一个事件驱动系统,但是并不像 asyncio 那样有复杂的调度过程,而仅仅是同步地在某些操作发生时调用。
它的流程大概是这样:
- 信号定义者:在框架代码中定义信号(使用
Signal
类),并在适当时机发送信号(signal.send()
)以触发信号处理函数 - 信号使用者:一般在业务配置(
AppConfig
)中注册信号处理函数(signal.connect()
),当信号被发送时,这些处理函数会被 Django 框架执行
举一个 Django auth 中的例子,无关代码被略去:
## 定义
# django.contrib.auth.signals 中定义了 user_logged_in signal
from django.dispatch import Signal
user_logged_in = Signal(providing_args=['request', 'user'])
# django.contrib.auth.login 处的代码,表明 login 最后被调用时,最后会触发信号
def login(request, user, backend=None):
# ...
user_logged_in.send(sender=user.__class__, request=request, user=user)
## 使用
# Django Auth 中本身也使用了这个信号,用于用户登录时更新其最后登录时间
# django.contrib.auth.apps.AuthConfig.ready
class AuthConfig(AppConfig):
def ready(self):
from .models import update_last_login
user_logged_in.connect(update_last_login, dispatch_uid='update_last_login')