教你如何在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分析git log日志示例
Feb 27 Python
python实现按行切分文本文件的方法
Apr 18 Python
python中的字典使用分享
Jul 31 Python
Django自定义插件实现网站登录验证码功能
Apr 19 Python
基于Django contrib Comments 评论模块(详解)
Dec 08 Python
对python中for、if、while的区别与比较方法
Jun 25 Python
零基础使用Python读写处理Excel表格的方法
May 02 Python
Python3 批量扫描端口的例子
Jul 25 Python
Python的缺点和劣势分析
Nov 19 Python
Pytorch中的自动求梯度机制和Variable类实例
Feb 29 Python
PyQt5 文本输入框自动补全QLineEdit的实现示例
May 13 Python
python获得命令行输入的参数的两种方式
Nov 02 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 页面执行时间计算代码
2008/12/04 PHP
怎样去阅读一份php源代码
2009/08/21 PHP
php数据结构 算法(PHP描述) 简单选择排序 simple selection sort
2011/08/09 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
Yii2 批量插入、更新数据实例
2017/03/15 PHP
php+ajax实现文件切割上传功能示例
2020/03/03 PHP
用showModalDialog弹出页面后,提交表单总是弹出一个新窗口
2009/07/18 Javascript
javascript下4个跨浏览器必备的函数
2010/03/07 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
jquery 操作DOM的基本用法分享
2012/04/05 Javascript
JS 退出系统并跳转到登录界面的实现代码
2013/06/29 Javascript
jquery 实现窗口的最大化不论什么情况
2013/09/03 Javascript
jQuery 取值、赋值的基本方法整理
2014/03/31 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
2017/07/21 Javascript
node基于puppeteer模拟登录抓取页面的实现
2018/05/09 Javascript
ES6小技巧之代替lodash
2019/06/07 Javascript
微信域名检测接口调用演示步骤(含PHP、Python)
2019/12/08 Javascript
Ajax获取node服务器数据的完整步骤
2020/09/20 Javascript
原生JavaScript实现五子棋游戏
2020/11/09 Javascript
[00:32]2016完美“圣”典风云人物:Maybe宣传片
2016/12/05 DOTA
Python中列表与元组的乘法操作示例
2018/02/10 Python
使用matplotlib中scatter方法画散点图
2019/03/19 Python
详解PyCharm+QTDesigner+PyUIC使用教程
2019/06/13 Python
Python ORM框架Peewee用法详解
2020/04/29 Python
利用python对mysql表做全局模糊搜索并分页实例
2020/07/12 Python
Python3爬虫mitmproxy的安装步骤
2020/07/29 Python
python 多进程和协程配合使用写入数据
2020/10/30 Python
爱尔兰灯和灯具网上商店:Lights.ie
2018/03/26 全球购物
什么是Assembly(程序集)
2014/09/14 面试题
单位办理社保介绍信
2014/01/10 职场文书
商场端午节活动方案
2014/01/29 职场文书
初二生物教学反思
2014/02/03 职场文书
医学专业应届生的自我评价
2014/02/28 职场文书
晨会主持词
2014/03/17 职场文书
村庄绿化方案
2014/05/07 职场文书
2014业务员年终工作总结
2014/12/09 职场文书