django包含了一个“信号分配器”使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者,这是特别有用的设计因为有些代码对某些事件是特别感兴趣的,比如删除动作。

为此,django提供了很多内置的信号,比如一些常用的功能(以几个在django.db.models.signal目录下的信号为例):

  • save:pre_save和post_save
  • delete:pre_delete和post_delete
  • change:m2m_changed

如果你想了解更多,可以查阅django的内置信号文档,本节的最后也会有一个所有内置信号的简略介绍。

监听信号

要想接受信号,你首先要注册一个接收器函数,当信号被Signal.connect()方法发射的时候,这个函数会被调用

Signal.connect(receiver[,sender=None,weak=True,dispatch_uid=None])

参数解释:

  • receiver:连接到这个信号的回调函数
  • sender:信号的发送者
  • weak:是否是弱引用,默认是真。因此,如果你的接收器是是一个本地函数,会被当做垃圾回收,如果你不想,请在使用connect()方法的时候使用weak=False
  • dispatch_uid:一个唯一的标识符给信号接收器,避免重复的信号被发送

下面让我们来看一个具体的例子来解释这些参数吧吧,这个例子以request_finished信号(每个HTTP请求结束的时候会被调用):

回调函数receiver

回调函数可以是一个函数或者方法,比如我们可以这样定义一个接收器:

  1. def my_callback(sender, **kwargs):
  2. print "Request finished!"

注意的是所有的信号处理器都需要这两个参数:sender和**kwargs。因为所有的信号都是发送关键字参数的,可能你处理的时候没有任何参数,但不意味着在处理的过程中(在你写的处理函数之前)有任何的参数生成,如果没有传**kwargs参数的话,可能会发生问题;基于这样的考虑,这两个参数都是必须的。

连接到你的receiver回调函数

有两种方法可以把信号和接收器连接到一起:

connect方法

  1. from django.core.signals import request_finished
  2.  
  3. request_finished.connect(my_callback)

装饰器方法

  1. from django.core.signals import request_finished
  2. from django.dispatch import receiver
  3.  
  4. @receiver(request_finished)
  5. def my_callback(sender, **kwargs):
  6. print "Request finished!"

这样配置之后,每次HTTP接受的时候都会调用这个接收器回调函数了

绑定特定的发送者

记上面之后,你会不会想到这样的一个问题:每次都调用,会不会很烦啊?如果是我的话,我肯定觉得很烦,毕竟我不是想接受所有人的信号的,所以你需要设置sender关键字参数

第二个知识:每一类的信号都对应着特定的发送者,所以要绑定发送者也得绑定对应的发送者类型,例如,request_finished对应的是handler class,而pre_save对应则是model class

下面我们以pre-save为例子绑定特定的发送者(模型):

  1. from django.db.models.signals import pre_save
  2. from django.dispatch import receiver
  3. from myapp.models import MyModel
  4.  
  5. @receiver(pre_save, sender=MyModel)
  6. def my_handler(sender, **kwargs):

预防重复的信号

使用dispatch_uid关键字参数

  1. request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

说完了如何监听一个信号,下面我们继续讲解定义和发送信号吧】

定义信号

class Signal([providing_args=list])

所有的信号都是django.dispatch.Signal的实例,参数providing_args是一个信号提供给监听器的参数名的列表,比如:

  1. import django.dispatch
  2.  
  3. pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

这段代码定义了一个pizza_done的信号,参数有toppings和size

发送信号

有两个方法发送信号

Signal.send(sender,**kwargs)

Signal.send_robust(sender,**kwargs)

sender参数是必须的,关键字参数可选

  1. class PizzaStore(object):
  2. ...
  3.  
  4. def send_pizza(self, toppings, size):
  5. pizza_done.send(sender=self, toppings=toppings, size=size)

这两种方法都返回一个元组对[(receiver,respose),...]的列表,一个代表被调用的receiver回调函数和他们的response的列表

这两种方法的区别在于send不会捕捉任何的异常,(放任错误的传播),而send_robust则是捕捉所有的异常,并确保每个接收器都知道这个信号(发生错误了)(如果发生错误的话,错误实体和发生错误的接收器作为一个元组对一起返回给那个列表

断开信号

Signal.disconnect([receiver=None,sender=None,weak=True,dispatch_uid=None)

和监听信号类似

receiver参数用来指明那个接收器被断开,如果使用了dispatch_uid的话,receiver可以为None

总结,你可以使用django自带的信号,也可以自定义自己的信号,信号可以connect,可以send也可以disconnect等等

23:django 信号(signal)的更多相关文章

  1. Django 信号signal

    序言 Django自带一套信号机制来帮助我们在框架的不同应用位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将信号(signals)发送给一组接收者(r ...

  2. django信号 signal

    django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(rec ...

  3. Django 详解 信号Signal

    Django信号 Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. Model signals pre_init # ...

  4. Django中信号signal针对model的使用

    Django中实现对数据库操作的记录除了使用[开源插件]还可以使用信号signal独立实现 信号机制-观察者模式-发布与订阅:signal - 配置 # 文件路径:Django/myapps/__in ...

  5. 第六章:Django 综合篇 - 8:信号 signal

    django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(rec ...

  6. flask,scrapy,django信号

    简介 Django.Flask.scrapy都包含了一个“信号分配器”,使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒. 通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒 ...

  7. pythonのdjango 信号

    一.内置信号 Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. Model signals pre_init # d ...

  8. django信号浅谈

    Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. 1.Django内置信号 Model signals pre_in ...

  9. django信号

    什么是信号? 信号是在某个操作前或后自动触发一些操作. 信号是通知,是一种状态,相当于在某种状态下发特定的消息 --为了实现代码层解耦 村长博客:http://www.cnblogs.com/legu ...

随机推荐

  1. BZOJ3144:[HNOI2013]切糕——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3144 看着很像网络流,但是费用流貌似无法解决这个问题,其实甚至连忽略d的情况都做不到. 最小割? ...

  2. 使用 Intel HAXM 为eclipse安卓模拟器加速

    一.下载haxm安装 https://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-ma ...

  3. selenium - webdriver常用方法

    先定位元素,定位元素后,需要对元素进行后续操作,单击按钮/输入文本,等等. from selenium import webdriver driver = webdriver.Chrome() dri ...

  4. SPOJ - HIGH :Highways (生成树计数)

    Highways 题目链接:https://vjudge.net/problem/SPOJ-HIGH Description: In some countries building highways ...

  5. idea 多模块引用

    roma-server 引用common-utils的类,所以在roma-server 的pom中配置 <dependency> <groupId>org.springfram ...

  6. 自己做的jquery的autocomplete的一个例子

    转载自:http://dada-fangfang.iteye.com/blog/695464 首先下载jquery.js和jquery.autocomplete.js 注意:jquery.js 要放在 ...

  7. maven插件理解

    maven插件的主要功能是对用到的jar包进行管理,jar包先从本地仓库中获取,如果没有找到,则从远处中央仓库下载(需要联外网).本地仓库中的jar包可供所有maven工程使用,属于公共模块. mav ...

  8. Packet Tracer 5.0 构建CCNA实验(2)—— 配置VLAN

    Packet Tracer 5.0 构建CCNA实验(2)—— 配置VLAN Vlan(Virtual Local Area Network) 即虚拟局域网.VLAN可以把同一个物理网络划分为多个逻辑 ...

  9. tomcat优化总结【持续更新】

    配置优化 <Connector port=" maxThreads=" URIEncoding="UTF-8" maxKeepAliveRequests= ...

  10. Golang向Templates 插入对象的值

    Go对象可以插入到template中,然后把对象的值表现在template中,你可以一层层的分解这个对象,去找他的子字段,当前对象用'.'来表示,所以当当前对象是一个string的时候,你可以用{{. ...