教你如何在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使用pyhook监控键盘并实现切换歌曲的功能
Jul 18 Python
Python导入txt数据到mysql的方法
Apr 08 Python
Python内置的HTTP协议服务器SimpleHTTPServer使用指南
Mar 30 Python
Python随机数random模块使用指南
Sep 09 Python
python实现斐波那契数列的方法示例
Jan 12 Python
Django的分页器实例(paginator)
Dec 01 Python
PyQt5每天必学之切换按钮
Aug 20 Python
Python数据持久化shelve模块用法分析
Jun 29 Python
Python根据欧拉角求旋转矩阵的实例
Jan 28 Python
如何用Python做一个微信机器人自动拉群
Jul 03 Python
python pygame实现挡板弹球游戏
Nov 25 Python
Django实现将一个字典传到前端显示出来
Apr 03 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
require(),include(),require_once()和include_once()的异同
2007/01/02 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
php重定向的三种方法分享
2012/02/22 PHP
PHP采集静态页面并把页面css,img,js保存的方法
2014/12/23 PHP
Laravel+jQuery实现AJAX分页效果
2016/09/14 PHP
如何打开php的gd2库
2017/02/09 PHP
Laravel中错误与异常处理的用法示例
2018/09/16 PHP
laravel框架查询数据集转为数组的两种方法
2019/10/10 PHP
js获取div高度的代码
2008/08/09 Javascript
JS对象转换为Jquery对象实现代码
2013/12/29 Javascript
JavaScript 学习笔记之数据类型
2015/01/14 Javascript
jQuery实现响应鼠标背景变化的动态菜单效果代码
2015/08/27 Javascript
js实现开启密码大写提示
2016/12/21 Javascript
JS监听滚动和id自动定位滚动
2018/12/18 Javascript
js实现圆形显示鼠标单击位置
2020/02/11 Javascript
vue使用map代替Aarry数组循环遍历的方法
2020/04/30 Javascript
微信小程序学习总结(二)样式、属性、模板操作分析
2020/06/04 Javascript
vue中父子组件的参数传递和应用示例
2021/01/04 Vue.js
[07:57]DOTA2热力大趴狂欢夜 广州站活动回顾
2013/11/27 DOTA
[03:26]回顾2015国际邀请赛中国区预选赛
2015/06/09 DOTA
Linux中安装Python的交互式解释器IPython的教程
2016/06/13 Python
Flask框架的学习指南之开发环境搭建
2016/11/20 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
2017/12/03 Python
Python之list对应元素求和的方法
2018/06/28 Python
selenium + python 获取table数据的示例讲解
2018/10/13 Python
Python中类似于jquery的pyquery库用法分析
2019/12/02 Python
python3中关于excel追加写入格式被覆盖问题(实例代码)
2020/01/10 Python
python 数据分析实现长宽格式的转换
2020/05/18 Python
Python filter()及reduce()函数使用方法解析
2020/09/05 Python
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
原材料检验岗位职责
2014/03/15 职场文书
2014机关干部学习“焦裕禄精神”思想汇报
2014/09/19 职场文书
2014年幼儿园工作总结
2014/11/10 职场文书
男人帮观后感
2015/06/18 职场文书
每日六道java新手入门面试题,通往自由的道路
2021/06/30 Java/Android
Windows Server 2012 R2服务器安装与配置的完整步骤
2022/07/15 Servers