教你如何在Django 1.6中正确使用 Signal


Posted in Python onJune 22, 2014

简单回答是: 在其他方法无法使用的情况下, 才最后考虑使用signal.

因为新的django开发人员得知signal之后, 往往会很高兴去使用它. 他们在能使用signal的地方就使用signal, 并且这是他们觉得自己是django专家一样. 然而, 像这样编码一段时间后, django项目就会变得异常复杂, 许多内容都纠结在一起无法解开.

许多开发者也会将django signal和异步消息列队(例如celery)搞混. signal是同步处理, 因此通过signal调用大处理量的进程时并无法提高性能. 事实上, 将这些需要大处理量的进程移到signal中被视作是一种不好的习惯.

1. 何时使用signal

以下情况不要使用signal:

signal与一个model紧密相关, 并能移到该model的save()时
signal能使用model manager代替时
signal与一个view紧密相关, 并能移到该view中时
以下情况可以使用signal:

signal的receiver需要同时修改对多个model时
将多个app的相同signal引到同一receiver中处理时
在某一model保存之后将cache清除时
无法使用其他方法, 但需要一个被调函数来处理某些问题时
2. Signal的代替方法

使用mod而来manager

以下代码演示了当用户创建Event model时, 需要通知管理员, 如果改写model中的post_save(), 则需要添加额外的逻辑来区分用户还是管理员:

# myapp/managers.py
 from django.db import models

 class EventManager(models.Manager):

 def create_event(self, title, start, end, creator):
 event = self.model(title=title, start=start, end=end, creator=creator)
 event.save()
 event.notify_admins()
 return event

在model中设置model manager:

# myapp/models.py
 from django.conf import settings
 from django.core.mail import mail_admins
 from django.db import models

 from model_utils.models import TimeStampedModel
 from .managers import EventManager

 class Event(TimeStampedModel):

 STATUS_UNREVIEWED, STATUS_REVIEWED = (0, 1)
 STATUS_CHOICES = (
 (STATUS_UNREVIEWED, "Unreviewed"),
 (STATUS_REVIEWED, "Reviewed")
 )

 title = models.CharField(max_length=100)
 start = models.DateTimeField()
 end = model.dateTimeField()
 status = models.IntegerField(choices=STATUS_CHOICES, default=STATUS_UNREVIEWED)
 creator = models.ForeignField(settings.AUTH_USER_MODEL)
 objects = EventManager()

 def notify_admins(self):
 subject = "{user} submitted a new event!".format(user=self.creator.get_full_name())
 message = """TITLE: {title}
 START: {start}
 END: {end}""".format(title=self.title, start=self.start, end=self.end)
 mail_admins(subject=subject, message=message, fail_silently=False)

在view中使用create_event()代替create()时, 便会通知管理员了.

在其他代码中验证model

如果你使用pre_save signal来验证某一model, 则应当尝试自己写一个validator取代之. 如果验证是通过ModelForm时, 通过改写clean()实现验证.

使用model的save()和delete()

如果使用pre_save 或 post_save signal, 如果可以, 则将这些代码移到model的save()方法中.

同样如果使用pre_delete 或 post_delete signal, 如果可以, 则将这些代码移到model的delte()方法中.

使用其他代码代替signal

如果可能, 我们可以将signal的逻辑使用其他帮助程序实现.

Python 相关文章推荐
python使用线程封装的一个简单定时器类实例
May 16 Python
在Python的列表中利用remove()方法删除元素的教程
May 21 Python
轻松实现python搭建微信公众平台
Feb 16 Python
python编程实现希尔排序
Apr 13 Python
Python即时网络爬虫项目启动说明详解
Feb 23 Python
python获取程序执行文件路径的方法(推荐)
Apr 26 Python
python的pyecharts绘制各种图表详细(附代码)
Nov 11 Python
在Anaconda3下使用清华镜像源安装TensorFlow(CPU版)
Apr 19 Python
Python reduce函数作用及实例解析
May 08 Python
Python pip install之SSL异常处理操作
Sep 03 Python
tensorflow中的梯度求解及梯度裁剪操作
May 26 Python
python游戏开发之pygame实现接球小游戏
Apr 22 Python
python抓取网页时字符集转换问题处理方案分享
Jun 19 #Python
python在linux中输出带颜色的文字的方法
Jun 19 #Python
解决windows下Sublime Text 2 运行 PyQt 不显示的方法分享
Jun 18 #Python
win7 下搭建sublime的python开发环境的配置方法
Jun 18 #Python
Python写的贪吃蛇游戏例子
Jun 16 #Python
Python中的yield浅析
Jun 16 #Python
python中使用enumerate函数遍历元素实例
Jun 16 #Python
You might like
谈谈PHP语法(2)
2006/10/09 PHP
深入理解PHP原理之错误抑制与内嵌HTML分析
2011/05/02 PHP
用PHP实现弹出消息提示框的两种方法
2013/12/17 PHP
redis查看连接数及php模拟并发创建redis连接的方法
2016/12/15 PHP
PHP标准库(PHP SPL)详解
2019/03/16 PHP
用PHP做了一个领取优惠券活动的示例代码
2019/07/05 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
ASP.NET jQuery 实例4(复制TextBox的文本到本地剪贴板上)
2012/01/13 Javascript
jquery ajax例子返回值详解
2012/09/11 Javascript
javascript自适应宽度的瀑布流实现思路
2013/02/20 Javascript
js中生成map对象的方法
2014/01/09 Javascript
js实现通用的微信分享组件示例
2014/03/10 Javascript
用Jquery.load载入页面后样式没了页面混乱的解决方法
2014/10/20 Javascript
浅谈Javascript如何实现匀速运动
2014/12/19 Javascript
javascript实现手机震动API代码
2015/08/05 Javascript
Jquery插件easyUi实现表单验证示例
2015/12/15 Javascript
使用Angular.js实现简单的购物车功能
2016/11/21 Javascript
js正则表达式最长匹配(贪婪匹配)和最短匹配(懒惰匹配)用法分析
2016/12/27 Javascript
JavaScript Base64 作为文件上传的实例代码解析
2017/02/14 Javascript
Javascript中绑定click事件的四种方式介绍
2018/10/26 Javascript
微信小程序之swiper滑动面板用法示例
2018/12/04 Javascript
[28:48]《真视界》- 2017年国际邀请赛
2017/09/27 DOTA
[01:15]PWL S2开团时刻第二期——他们杀 我就白给
2020/11/25 DOTA
用tensorflow构建线性回归模型的示例代码
2018/03/05 Python
python爬虫获取新浪新闻教学
2018/12/23 Python
以SQLite和PySqlite为例来学习Python DB API
2020/02/05 Python
浅谈sklearn中predict与predict_proba区别
2020/06/28 Python
python字典通过值反查键的实现(简洁写法)
2020/09/30 Python
naturalizer加拿大官网:美国娜然女鞋
2017/04/04 全球购物
创联软件面试题笔试题
2012/10/07 面试题
业务助理岗位职责
2013/11/18 职场文书
社区服务活动总结
2014/05/07 职场文书
教师批评与自我批评总结
2014/10/16 职场文书
2019大学生实习报告
2019/06/21 职场文书
你真的会用Mysql的explain吗
2022/03/31 MySQL
React四级菜单的实现
2022/04/08 Javascript