django之signal机制分析

Posted on 2018-02-23 21:15  王将军之武库  阅读(280)  评论(0)    收藏  举报

django的signal在djangobb中的使用:

from django.db.models.signals import post_save
from django.dispatch import receiver

from djangobb_forum.subscription import notify_topic_subscribers
from djangobb_forum.models import Topic, Post

#post_save:为信号对象,Post为发出信号的对象
@receiver(post_save, sender=Post, dispatch_uid='djangobb_post_save')
def post_saved(instance, **kwargs):#该函数为信号处理器
    created = kwargs.get('created')
    post = instance
    topic = post.topic

    if created:
        topic.last_post = post
        topic.post_count = topic.posts.count()
        topic.updated = timezone.now()
        profile = post.user.forum_profile
        profile.post_count = post.user.posts.count()
        profile.save(force_update=True)
        notify_topic_subscribers(post)
    topic.save(force_update=True)

以上代码使得每次新建一个post时,都会修改topic的内容

def receiver(signal, **kwargs):
    """
    A decorator for connecting receivers to signals. Used by passing in the
    signal (or list of signals) and keyword arguments to connect::

        @receiver(post_save, sender=MyModel)
        def signal_receiver(sender, **kwargs):
            ...

        @receiver([post_save, post_delete], sender=MyModel)
        def signals_receiver(sender, **kwargs):
            ...
    """
    def _decorator(func):
        if isinstance(signal, (list, tuple)):
            for s in signal:
                s.connect(func, **kwargs)
        else:
            signal.connect(func, **kwargs)
        return func
    return _decorator

 修饰器receiver调用信号的connect函数,添加了信号的处理器。

signal调用send函数时就会调用到signal的receiver,那post_save信号的send函数什么时候调用,由谁调用呢?看django的Class Model类的save函数中的一段代码:

# Signal that the save is complete
        if not meta.auto_created:#发出信号。
            signals.post_save.send(sender=origin, instance=self, created=(not updated),
                                   update_fields=update_fields, raw=raw, using=using)

调用了signal的send函数。也就是说,保存model实例时就会触发signal,调用send。

post_save的定义:

post_save = ModelSignal(providing_args=["instance", "raw", "created", "using", "update_fields"], use_caching=True)

限定信号的args

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3