教你如何在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支持断点续传的多线程下载示例
Jan 16 Python
Python 爬虫之超链接 url中含有中文出错及解决办法
Aug 03 Python
python cx_Oracle的基础使用方法(连接和增删改查)
Nov 19 Python
python实现抖音视频批量下载
Jun 20 Python
python程序快速缩进多行代码方法总结
Jun 23 Python
python opencv minAreaRect 生成最小外接矩形的方法
Jul 01 Python
Python分割训练集和测试集的方法示例
Sep 19 Python
python反转列表的三种方式解析
Nov 08 Python
Python常用类型转换实现代码实例
Jul 28 Python
基于Python爬取京东双十一商品价格曲线
Oct 23 Python
Django使用echarts进行可视化展示的实践
Jun 10 Python
Python中使用Opencv开发停车位计数器功能
Apr 04 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
967 个函式
2006/10/09 PHP
php 更新数据库中断的解决方法
2009/06/05 PHP
注意:php5.4删除了session_unregister函数
2013/08/05 PHP
Codeigniter实现发送带附件的邮件
2015/03/19 PHP
PHP函数checkdnsrr用法详解(Windows平台用法)
2016/03/21 PHP
PHP多进程编程之僵尸进程问题的理解
2017/10/15 PHP
Javascript 写的简单进度条控件
2008/01/22 Javascript
JavaScript和CSS通过expression实现Table居中显示
2013/06/28 Javascript
setInterval()和setTimeout()的用法和区别示例介绍
2013/11/17 Javascript
JavaScript—window对象使用示例
2013/12/09 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
AngularJS实现select的ng-options功能示例
2017/07/12 Javascript
jQuery判断网页是否已经滚动到浏览器底部的实现方法
2017/10/27 jQuery
浅谈Webpack下多环境配置的思路
2018/06/27 Javascript
详解puppeteer使用代理
2018/12/27 Javascript
微信小程序swiper禁止用户手动滑动代码实例
2019/08/23 Javascript
vue中watch和computed为什么能监听到数据的改变以及不同之处
2019/12/27 Javascript
Jquery Fade用法详解
2020/11/06 jQuery
[08:29]DOTA2每周TOP10 精彩击杀集锦vol.7
2014/06/25 DOTA
Python中的模块导入和读取键盘输入的方法
2015/10/16 Python
python 类对象和实例对象动态添加方法(分享)
2017/12/31 Python
Python 通配符删除文件的实例
2018/04/24 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
python获取本机所有IP地址的方法
2018/12/26 Python
Windows下实现将Pascal VOC转化为TFRecords
2020/02/17 Python
解决pycharm安装第三方库失败的问题
2020/05/09 Python
收集的22款给力的HTML5和CSS3帮助工具
2012/09/14 HTML / CSS
HTML5 video进入全屏和退出全屏的实现方法
2020/07/28 HTML / CSS
走群众路线学习笔记
2014/11/06 职场文书
防汛通知
2015/04/25 职场文书
2015年招生工作总结
2015/05/04 职场文书
2016形势与政策学习心得体会
2016/01/12 职场文书
车位出租协议书范本
2016/03/19 职场文书
2019最新公司租房合同(例文)
2019/07/18 职场文书
导游词之烟台威海蓬莱
2019/11/14 职场文书
JavaScript实现简单拖拽效果
2021/09/15 Javascript