###Signals是什么
为了回答这个问题,我们先来看下django官网对它的描述:
Django includes a “signal dispatcher” which helps allow decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.
大概意思是说:Django内部包含了一位“信号调度员”:当某事件在框架内发生时,它可以通知到我们的应用程序(处理函数)。 简而言之,当event
(事件)发生时,signals
(信号)允许若干 senders
(发送者)通知一组 receivers(接收者)。
很像js的事件驱动模型。关于事件驱动,我在上一篇文章中有谈论,这里不多说。
###有什么用的
在web开发中, 你可能会遇到下面这种场景:
在用户完成某个操作后, 自动去执行一些后续的操作. 譬如用户完成修改密码后,
你要发送一份确认邮件.
如果一个操作可能会触发多个后续事件, 此时使用signals会非常方便. 我们可以想要一下应用场景:
- sns中的事件通知, 如用户发表了一篇博文, 然后通知所有的好友
- 用户信息的更改的邮件通知
- 用户订制信息的邮件通知等
###如何使用
####常用的信号集:
- django.db.models.signals.pre_save model在save()前发送的信号
- django.db.models.signals.post_save model在save()后发送的信号
- django.db.models.signals.pre_delete
- django.db.models.signals.post_delete
####来自官网的例子
1
2
3
4
5
6
7
|
#使用装饰器
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
|
Connecting to signals sent by specific senders.
就是说我们只处理某个模型
发出的信号
1
2
3
4
5
6
7
|
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):
...
|
####自定义事件
在此使用一休哥同学给的例子,也是Django中现成的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#file:django\db\models\signals.py
from django.dispatch import Signal
post_syncdb = Signal(providing_args=["class", "app", "created_models",
"verbosity", "interactive"])
#-----------------------------------
#file:django\contrib\contenttypes\management.py
from django.db.models import signals
signals.post_syncdb.connect(update_contenttypes)
#-----------------------------------
#file:django\core\management\sql.py
def emit_post_sync_signal(created_models, verbosity, interactive, db):
# Emit the post_sync signal for every application.
for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
if verbosity >= 2:
print("Running post-sync handlers for application %s" % app_name)
models.signals.post_syncdb.send(sender=app, app=app,
created_models=created_models, verbosity=verbosity,
interactive=interactive, db=db)
|
更具体的实例可以参考:django拾遗之signal
###参考