教你如何在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之list和str比较
Sep 20 Python
python统计文本字符串里单词出现频率的方法
May 26 Python
Django框架中的对象列表视图使用示例
Jul 21 Python
Python 使用requests模块发送GET和POST请求的实现代码
Sep 21 Python
python+pyqt实现右下角弹出框
Oct 26 Python
Python实现读写INI配置文件的方法示例
Jun 09 Python
Pyinstaller打包.py生成.exe的方法和报错总结
Apr 02 Python
scrapy-redis源码分析之发送POST请求详解
May 15 Python
python过滤中英文标点符号的实例代码
Jul 15 Python
python  文件的基本操作 菜中菜功能的实例代码
Jul 17 Python
python 控制Asterisk AMI接口外呼电话的例子
Aug 08 Python
详解Python调用系统命令的六种方法
Jan 28 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
thinkphp使用phpmailer发送邮件的方法
2014/11/24 PHP
php截取html字符串及自动补全html标签的方法
2015/01/15 PHP
thinkphp分页集成实例
2017/07/24 PHP
PHP dirname简单使用代码实例
2020/11/13 PHP
javascript JSON操作入门实例
2010/04/16 Javascript
jQuery 表单验证扩展代码(一)
2010/10/11 Javascript
将HTMLCollection/NodeList/伪数组转换成数组的实现方法
2011/06/20 Javascript
Javascript:为input设置readOnly属性(示例讲解)
2013/12/25 Javascript
网页中表单按回车就自动提交的问题的解决方案
2014/11/03 Javascript
js给网页加上背景音乐及选择音效的方法
2015/03/03 Javascript
JavaScript实现的字符串replaceAll函数代码分享
2015/04/02 Javascript
ECMAScript6新增值比较函数Object.is
2015/06/12 Javascript
详解JavaScript中的异常处理方法
2015/06/16 Javascript
jquery+CSS实现的多级竖向展开树形TRee菜单效果
2015/08/24 Javascript
javascript中sort排序实例详解
2016/07/24 Javascript
引用jquery框架后出错的解决方法
2016/08/09 Javascript
微信公众号  提示:Unauthorized API function 问题解决方法
2016/12/05 Javascript
jQuery基于ajax操作json数据简单示例
2017/01/05 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
js实现加载页面就自动触发超链接的示例
2017/08/31 Javascript
Vue.js实现的计算器功能完整示例
2018/07/11 Javascript
bootstrap里bootstrap动态加载下拉框的实例讲解
2018/08/10 Javascript
Python collections模块实例讲解
2014/04/07 Python
在PyCharm中三步完成PyPy解释器的配置的方法
2018/10/29 Python
Pycharm 文件更改目录后,执行路径未更新的解决方法
2019/07/19 Python
python基础 range的用法解析
2019/08/23 Python
HTML5中使用postMessage实现两个网页间传递数据
2016/06/22 HTML / CSS
阿根廷网上配眼镜:SmartBuyGlasses阿根廷
2016/08/19 全球购物
如何开启linux的ssh服务
2015/02/14 面试题
夜大毕业自我鉴定
2013/10/11 职场文书
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
大学校园活动策划书
2014/02/04 职场文书
2015年度信用社工作总结
2015/05/04 职场文书
联谊活动总结范文
2015/05/09 职场文书
教师旷工检讨书
2015/08/15 职场文书
mysql连接查询中and与where的区别浅析
2021/07/01 MySQL