教你如何在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学习笔记(二)基础语法
Jun 06 Python
Python contextlib模块使用示例
Feb 18 Python
python实现的文件同步服务器实例
Jun 02 Python
Python 3.6 性能测试框架Locust安装及使用方法(详解)
Oct 11 Python
用python写扫雷游戏实例代码分享
May 27 Python
tensorflow使用神经网络实现mnist分类
Sep 08 Python
查看Python依赖包及其版本号信息的方法
Aug 13 Python
Python Pandas对缺失值的处理方法
Sep 27 Python
详解Python time库的使用
Oct 10 Python
Python 解码Base64 得到码流格式文本实例
Jan 09 Python
解决Python命令行下退格,删除,方向键乱码(亲测有效)
Jan 16 Python
python 提高开发效率的5个小技巧
Oct 19 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
《Re:从零开始的异世界生活 冰结之绊》
2020/04/09 日漫
PHP iconv 解决utf-8和gb2312编码转换问题
2010/04/12 PHP
无刷新动态加载数据 滚动条加载适合评论等页面
2013/10/16 PHP
php检索或者复制远程文件的方法
2015/03/13 PHP
PHP匿名函数和use子句用法实例
2016/03/16 PHP
thinkphp5.1 文件引入路径问题及注意事项
2018/06/13 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
javascript 随机展示头像实现代码
2011/12/06 Javascript
JQuery的自定义事件代码,触发,绑定简单实例
2013/08/01 Javascript
JavaScript制作windows经典扫雷小游戏
2015/03/31 Javascript
jQuery中fadein与fadeout方法用法示例
2016/09/16 Javascript
JS控制FileUpload的上传文件类型实例代码
2016/10/07 Javascript
React Native之ListView实现九宫格效果的示例
2017/08/02 Javascript
纯JavaScript实现实时反馈系统时间
2017/10/26 Javascript
bmob js-sdk 在vue中的使用教程
2018/01/21 Javascript
vue.js 获取select中的value实例
2018/03/01 Javascript
解决vue组件中click事件失效的问题
2019/11/09 Javascript
微信小程序如何获取地址
2019/12/24 Javascript
解决vue+ element ui 表单验证有值但验证失败问题
2020/01/16 Javascript
[02:53]2018年度DOTA2最佳战队-完美盛典
2018/12/17 DOTA
[43:43]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第三场 11.29
2020/12/02 DOTA
分享15个最受欢迎的Python开源框架
2014/07/13 Python
python实现绘制树枝简单示例
2014/07/24 Python
Win10环境python3.7安装dlib模块趟过的坑
2019/08/01 Python
Python读取csv文件实例解析
2019/12/30 Python
利物浦足球俱乐部官方网上商店:Liverpool FC Official Store
2018/01/13 全球购物
ASICS印度官方网站:日本专业运动品牌
2020/06/20 全球购物
活动总结怎么写啊
2014/05/07 职场文书
查摆问题整改措施
2014/10/24 职场文书
工作简报范文
2015/07/21 职场文书
吃通javascript正则表达式
2021/04/21 Javascript
使用numpy实现矩阵的翻转(flip)与旋转
2021/06/03 Python
Nginx反向代理至go-fastdfs案例讲解
2021/08/02 Servers
Redis如何使用乐观锁(CAS)保证数据一致性
2022/03/25 Redis
spring注解 @PropertySource配置数据源全流程
2022/03/25 Java/Android
win11自动弹出虚拟键盘怎么关闭? Win11关闭虚拟键盘的技巧
2023/01/09 数码科技