django中的signals

django中得signals和操作系统(linux)中的signal完全是两会事,后者的signal是软件中断,提供一种处理异步事件得方法,信号是系统定义好的,可用作进程间传递消息得一种方法,而django中的信号只是一个普通的类,不能跨进程,看其代码更像一个。。。callback。。。

django signal类定义在django/dispatch/dispatch.py中

  1. class Signal(object):  
  2.    
  3.     def __init__(self, providing_args=None):  
  4.         #providing_args 定义receiver调用参数格式,为None也没关系  
  5.         self.receivers = []  
  6.         ......  
  7.   
  8.     def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):  
  9.         #看清楚了,其实就是把receiver保存起来,receiver是一个函数对象,就是该signal得handler  
  10.         ......  
  11.         if dispatch_uid:  
  12.             lookup_key = (dispatch_uid, _make_id(sender))  
  13.         else:  
  14.             lookup_key = (_make_id(receiver), _make_id(sender))  
  15.   
  16.         ......  
  17.   
  18.         self.lock.acquire()  
  19.         try:  
  20.             for r_key, _ in self.receivers:  
  21.                 if r_key == lookup_key:  
  22.                     break  
  23.             else:  
  24.                 self.receivers.append((lookup_key, receiver))  
  25.         finally:  
  26.             self.lock.release()  
  27.   
  28.     def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None):  
  29.         #取消connect,把receiver从self.receivers删除就行了  
  30.         ......  
  31.            
  32.     def send(self, sender, **named):  
  33.         #在事件发生时调用,发出信号,如有receive connect该信号,则调用之  
  34.         responses = []  
  35.         if not self.receivers:  
  36.             return responses  
  37.   
  38.         for receiver in self._live_receivers(_make_id(sender)):  
  39.             response = receiver(signal=self, sender=sender, **named)  
  40.             responses.append((receiver, response))  
  41.         return responses  
  42.   
  43.     def send_robust(self, sender, **named):  
  44.         #基本同上  
  45.         ......  
  46.     def _live_receivers(self, senderkey):  
  47.         #从self.receivers中找出相应得receiver  
  48.         ......  
  49.     def _remove_receiver(self, receiver):  
  50.         """ 
  51.         Remove dead receivers from connections. 
  52.         """  
  53.         ......  

整个信号得定义就这么简单,再来看看django中已定义好得一些signal, 在django/db/models/signal.py中

  1. from django.dispatch import Signal  
  2.   
  3. class_prepared = Signal(providing_args=["class"])  
  4.   
  5. pre_init = Signal(providing_args=["instance""args""kwargs"])  
  6. post_init = Signal(providing_args=["instance"])  
  7.   
  8. pre_save = Signal(providing_args=["instance""raw""using"])  
  9. post_save = Signal(providing_args=["instance""raw""created""using"])  
  10.   
  11. pre_delete = Signal(providing_args=["instance""using"])  
  12. post_delete = Signal(providing_args=["instance""using"])  
  13.   
  14. post_syncdb = Signal(providing_args=["class""app""created_models""verbosity""interactive"])  
  15.   
  16. m2m_changed = Signal(providing_args=["action""instance""reverse""model""pk_set""using"])  


他们中比如pre_init是在model实例之前会触发, post_init是在model实例化之后触发。 pre_save是在保存之前触发, post_save是保存之后触发。他们真正得实现机制看代码django/db/models/base.py处, 如下:

  1. class Model(object):  
  2.    ......  
  3.   
  4.     def __init__(self, *args, **kwargs):  
  5.         signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs)  
  6.   
  7.        ......  
  8.         signals.post_init.send(sender=self.__class__, instance=self)  
  9.       
  10.     def save_base(self, raw=Falsecls=None, origin=None, force_insert=False,  
  11.             force_update=False, using=None):  
  12.          
  13.         ......  
  14.         if origin and not meta.auto_created:  
  15.             signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)  
  16.   
  17.        ......  
  18.   
  19.         # Signal that the save is complete  
  20.         if origin and not meta.auto_created:  
  21.             signals.post_save.send(sender=origin, instance=self,  
  22.                 created=(not record_exists), raw=raw, using=using)  
  23.       


so, that all

ps. 增加一个自定义signal得介绍

    1. import django.dispatch  
    2.   
    3. pizza_done = django.dispatch.Signal(providing_args=["toppings""size"])  
    4.   
    5. class PizzaStore(object):  
    6.     ...  
    7.   
    8.     def send_pizza(self, toppings, size):  
    9.         pizza_done.send(sender=self, toppings=toppings, size=size)  
    10.         ...  
    11.   
    12. def recv(sender, **kwargs):  
    13.     pass  
    14.   
    15. pizza_done.connect(recv)  
原文地址:https://www.cnblogs.com/lddhbu/p/2561384.html