教你如何在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字符转换
Sep 06 Python
Python的一些用法分享
Oct 07 Python
Python基本数据类型详细介绍
Mar 11 Python
python自动翻译实现方法
May 28 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
Jul 11 Python
Python常见排序操作示例【字典、列表、指定元素等】
Aug 15 Python
详解Python发送email的三种方式
Oct 18 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
python实现七段数码管和倒计时效果
Nov 23 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
Dec 10 Python
Python调用C/C++的方法解析
Aug 05 Python
linux中nohup和后台运行进程查看及终止
Jun 24 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并发对MYSQL造成压力的解决方法
2013/02/21 PHP
使用PHP静态变量当缓存的方法
2013/11/13 PHP
PHP错误Warning: Cannot modify header information - headers already sent by解决方法
2014/09/27 PHP
php阿拉伯数字转中文人民币大写
2015/12/21 PHP
PHP中的print_r 与 var_dump 输出数组
2016/06/13 PHP
JQUERY复选框CHECKBOX全选,取消全选
2008/08/30 Javascript
比较全面的event对像在IE与FF中的区别 推荐
2009/09/21 Javascript
javascript 带有滚动条的表格,标题固定,带排序功能.
2009/11/13 Javascript
使用pcs api往免费的百度网盘上传下载文件的方法
2016/03/17 Javascript
原生js实现autocomplete插件
2016/04/14 Javascript
基于jQuery实现滚动切换效果
2016/12/02 Javascript
Vue 2.0在IE11中打开项目页面空白的问题解决
2017/07/16 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
vue 页面加载进度条组件实例
2018/02/05 Javascript
vue弹窗消息组件的使用方法
2020/09/24 Javascript
详解Require.js与Sea.js的区别
2018/08/05 Javascript
详解ES6 Promise对象then方法链式调用
2018/10/20 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
手把手教你实现 Promise的使用方法
2020/09/02 Javascript
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
Python读取txt文件数据的方法(用于接口自动化参数化数据)
2018/06/27 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
Python for循环及基础用法详解
2019/11/08 Python
Tensorflow累加的实现案例
2020/02/05 Python
python+OpenCV实现图像拼接
2020/03/05 Python
Python with语句用法原理详解
2020/07/03 Python
详解Pycharm与anaconda安装配置指南
2020/08/25 Python
什么是虚拟内存?虚拟内存有什么优势?
2016/02/09 面试题
我的五年职业生涯规划
2014/01/23 职场文书
2014年大学生就业规划书
2014/04/04 职场文书
节约用水倡议书
2014/04/16 职场文书
大学自主招生推荐信
2014/05/10 职场文书
二手车转让协议书
2015/01/29 职场文书
工厂仓管员岗位职责
2015/04/01 职场文书
船舶调度指挥系统——助力智慧海事
2022/02/18 无线电
css清除浮动clearfix:after的用法详解(附完整代码)
2023/05/21 HTML / CSS