教你如何在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中使用全局日志时需要注意的问题
May 06 Python
Python装饰器实现几类验证功能做法实例
May 18 Python
Python实现输出某区间范围内全部素数的方法
May 02 Python
Python+selenium 获取一组元素属性值的实例
Jun 22 Python
python之验证码生成(gvcode与captcha)
Jan 02 Python
python-itchat 获取微信群用户信息的实例
Feb 21 Python
Linux下远程连接Jupyter+pyspark部署教程
Jun 21 Python
python3的print()函数的用法图文讲解
Jul 16 Python
开启Django博客的RSS功能的实现方法
Feb 17 Python
Django之全局使用request.user.username的实例详解
May 14 Python
使用Python-OpenCV消除图像中孤立的小区域操作
Jul 05 Python
python基于opencv批量生成验证码的示例
Apr 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
destoon实现不同会员组公司名称显示不同的颜色的方法
2014/08/22 PHP
初识laravel5
2015/03/02 PHP
PHP获取用户访问IP地址的5种方法
2016/05/16 PHP
PHPUnit测试私有属性和方法功能示例
2018/06/12 PHP
jquery中的$(document).ready()与window.onload的区别
2009/11/18 Javascript
xss文件页面内容读取(解决)
2010/11/28 Javascript
js禁止小键盘输入数字功能代码
2011/08/01 Javascript
扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
2011/12/08 Javascript
JS返回上一页实例代码通过图片和按钮分别实现
2013/08/16 Javascript
JS图片无缝、平滑滚动代码
2014/03/11 Javascript
jQuery源码解读之removeAttr()方法分析
2015/02/20 Javascript
JavaScript整除运算函数ceil和floor的区别分析
2015/04/14 Javascript
JavaScript实现select添加option
2015/07/03 Javascript
javascript禁止访客复制网页内容的实现代码
2015/08/05 Javascript
js添加事件的通用方法推荐
2016/05/15 Javascript
微信小程序 input输入及动态设置按钮的实现
2017/10/27 Javascript
Vue之Vue.set动态新增对象属性方法
2018/02/23 Javascript
node实现的爬虫功能示例
2018/05/04 Javascript
监控微信小程序中的慢HTTP请求过程详解
2019/07/05 Javascript
在python的WEB框架Flask中使用多个配置文件的解决方法
2014/04/18 Python
pytorch获取vgg16-feature层输出的例子
2019/08/20 Python
wxPython实现分隔窗口
2019/11/19 Python
OpenCV+Python--RGB转HSI的实现
2019/11/27 Python
python @propert装饰器使用方法原理解析
2019/12/25 Python
keras得到每层的系数方式
2020/06/15 Python
美国复古街头服饰精品店:Need Supply Co.
2017/02/22 全球购物
销售冠军获奖感言
2014/02/03 职场文书
物流毕业生个人的自我评价
2014/02/13 职场文书
挂牌仪式主持词
2014/03/20 职场文书
《翻越远方的大山》教学反思
2014/04/13 职场文书
市场推广策划方案
2014/06/02 职场文书
我的中国梦演讲稿小学篇
2014/08/19 职场文书
中韩经贸翻译专业大学生职业生涯规划范文
2014/09/18 职场文书
2014年幼儿园小班工作总结
2014/12/04 职场文书
厉行节约工作总结
2015/08/12 职场文书
python tkinter实现定时关机
2021/04/21 Python