文档章节

Django signal 信号

MtrS
 MtrS
发布于 2015/02/28 11:12
字数 1203
阅读 71
收藏 1
点赞 0
评论 0

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

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

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

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

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

connect方法

from django.core.signals import request_finished

request_finished.connect(my_callback)

装饰器方法

from django.core.signals import request_finished from django.dispatch import receiver

@receiver(request_finished) def my_callback(sender, **kwargs): print "Request finished!"

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

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

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

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

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):

预防重复的信号

使用dispatch_uid关键字参数

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

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

class Signal([providing_args=list])

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

import django.dispatch

pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

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

有两个方法发送信号

Signal.send(sender,**kwargs)

Signal.send_robust(sender,**kwargs)

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

class PizzaStore(object): ...

def send_pizza(self, toppings, size):
    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等等

© 著作权归作者所有

共有 人打赏支持
MtrS
粉丝 30
博文 474
码字总数 352132
作品 0
榆林
django signal使用步骤简记

步骤: 1.定义一个信号: 2.为信号添加回调函数: 3.实际调用

fromdtor ⋅ 2015/09/04 ⋅ 0

django 1.8 官方文档翻译:14-5 信号

信号 Django包含一个“信号的分发器”,允许解耦的应用在信号出现在框架的任何地方时,都能获得通知。简单来说,信号允许指定的 发送器通知一系列的接收器,一些操作已经发生了。当一些代码会...

apachecn_飞龙 ⋅ 2015/09/23 ⋅ 0

使django与数据库保持长连接

最近遇到一个很蛋疼的问题,写了一个后台管理系统, 由于是后台管理系统,所以使用频率不是很高,当django程序在闲置一段时间后,再次打开后台系统,就变得很慢,然后又好了。查了很多方面,...

请点赞 ⋅ 2014/02/26 ⋅ 12

Django中扩展User模型

官方其实是有资料的,不过在这里还是写的浅显点。 官方地址https://docs.djangoproject.com/en/dev/topics/auth/customizing/ 在实际开发过程中,django提供的user字段肯定是不够用的,比如用...

spider1983 ⋅ 2014/08/26 ⋅ 0

Django中的Signals和GenericForeignKey的使用

Signals 顾名思义,就是信号的意思。 Django的signals可以用来干什么呢?比如,论坛中别人给你发了一条消息,自动产生一个消息对象。 我们先来自定义一个信号 Message应用中的models.py fro...

shaohan ⋅ 2014/04/17 ⋅ 0

Django学习笔记(8)--- Signals和GenericForeignKey的使用

Signals 顾名思义,就是信号的意思。 Django的signals可以用来干什么呢?比如,论坛中别人给你发了一条消息,自动产生一个消息对象。 我们先来自定义一个信号 Message应用中的models.py fro...

Linktime ⋅ 2013/08/11 ⋅ 0

Django之信号

一、什么是信号 Django 提供一个“信号分发器”,允许解耦的应用在框架的其它地方发生操作时会被通知到。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。 二、D...

daibaiyang119 ⋅ 2017/11/01 ⋅ 0

python blinker 库学习

创建信号 信号通过signal()方法进行创建: >>> from blinker import signal >>> initialized = signal("initialized") >>> initialized is signal("initialized") True 每次调用signal('nam......

铁扇公主1 ⋅ 2017/04/07 ⋅ 0

Linux 信号signal处理函数

alarm(设置信号传送闹钟) 相关函数 signal,sleep 表头文件 #include 定义函数 unsigned int alarm(unsigned int seconds); 函数说明 alarm()用来设置信号SIGALRM在经过参数seconds指定的秒...

长平狐 ⋅ 2013/01/06 ⋅ 0

Linux 信号signal处理函数

alarm(设置信号传送闹钟) 相关函数 signal,sleep 表头文件 #include 定义函数 unsigned int alarm(unsigned int seconds); 函数说明 alarm()用来设置信号SIGALRM在经过参数seconds指定的秒...

晨曦之光 ⋅ 2012/03/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring发展历程总结

转自与 https://www.cnblogs.com/RunForLove/p/4641672.html 目前很多公司的架构,从Struts2迁移到了SpringMVC。你有想过为什么不使用Servlet+JSP来构建Java web项目,而是采用SpringMVC呢?...

onedotdot ⋅ 34分钟前 ⋅ 0

Python模块/包/库安装(6种方法)

Python模块/包/库安装(6种方法) 冰颖机器人 2016-11-29 21:33:26 一、方法1: 单文件模块 直接把文件拷贝到 $python_dir/Lib 二、方法2: 多文件模块,带setup.py 下载模块包(压缩文件zip...

cswangyx ⋅ 53分钟前 ⋅ 0

零基础学习大数据人工智能,学习路线篇!系统规划大数据之路?

大数据处理技术怎么学习呢?首先我们要学习Python语言和Linux操作系统,这两个是学习大数据的基础,学习的顺序不分前后。 Python:Python 的排名从去年开始就借助人工智能持续上升,现在它已经...

董黎明 ⋅ 今天 ⋅ 0

openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss ⋅ 今天 ⋅ 0

梳理

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 它是JS的状态容器,是一种解决问题的方式,所以即可以用于 react 也可以用于 vue。 需要理解其思想及实现方式。 应用中所有的 stat...

分秒 ⋅ 今天 ⋅ 0

Java 后台判断是否为ajax请求

/** * 是否是Ajax请求 * @param request * @return */public static boolean isAjax(ServletRequest request){return "XMLHttpRequest".equalsIgnoreCase(((HttpServletReques......

JavaSon712 ⋅ 今天 ⋅ 0

Redis 单线程 为何却需要事务处理并发问题

Redis是单线程处理,也就是命令会顺序执行。那么为什么会存在并发问题呢? 个人理解是,虽然redis是单线程,但是可以同时有多个客户端访问,每个客户端会有 一个线程。客户端访问之间存在竞争...

码代码的小司机 ⋅ 今天 ⋅ 0

到底会改名吗?微软GVFS 改名之争

微软去年透露了 Git Virtual File System(GVFS)项目,GVFS 是 Git 版本控制系统的一个开源插件,允许 Git 处理 TB 规模的代码库,比如 270 GB 的 Windows 代码库。该项目公布之初就引发了争...

linux-tao ⋅ 今天 ⋅ 0

笔试题之Java基础部分【简】【二】

1.静态变量和实例变量的区别 在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变...

anlve ⋅ 今天 ⋅ 0

Lombok简单介绍及使用

官网 通过简单注解来精简代码达到消除冗长代码的目的 优点 提高编程效率 使代码更简洁 消除冗长代码 避免修改字段名字时忘记修改方法名 4.idea中安装lombnok pom.xml引入 <dependency> <grou...

to_ln ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部