• 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)  
  • 相关阅读:
    oracle 工作中遇到的函数
    算法工作中使用的
    Windows下用PIP安装scipy出现no lapack/blas resources found
    Spring mvc 加载HTML静态页面
    Restful架构学习
    Python: Windows下pip安装库出错:Microsoft Visual C++ 9.0 is required < Unable to find vcvarsall.bat
    局域网内部访问问题
    安装mysql-connector-python
    Centos 安装 python2.7.10以及pip
    python2.7安装pip遇到ImportError: cannot import name HTTPSHandle
  • 原文地址:https://www.cnblogs.com/lddhbu/p/2561384.html
Copyright © 2020-2023  润新知