教你如何在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的Django框架中的中间件
Jul 24 Python
Python的Flask框架中集成CKeditor富文本编辑器的教程
Jun 13 Python
PyTorch上实现卷积神经网络CNN的方法
Apr 28 Python
Python3多进程 multiprocessing 模块实例详解
Jun 11 Python
详解Django-auth-ldap 配置方法
Dec 10 Python
自学python的建议和周期预算
Jan 30 Python
在TensorFlow中屏蔽warning的方式
Feb 04 Python
python实现连连看游戏
Feb 14 Python
python实现mean-shift聚类算法
Jun 10 Python
python中format函数如何使用
Jun 22 Python
cookies应对python反爬虫知识点详解
Nov 25 Python
解决Python import .pyd 可能遇到路径的问题
Mar 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
php获取YouTube视频信息的方法
2015/02/11 PHP
php模拟post提交数据的方法
2015/02/12 PHP
php获取网站百度快照日期的方法
2015/07/29 PHP
使用Javascript和DOM Interfaces来处理HTML
2006/10/09 Javascript
利用JQuery+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
2009/10/24 Javascript
javascript options属性集合操作代码
2009/12/28 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
2014/04/30 Javascript
Javascript基础教程之关键字和保留字汇总
2015/01/18 Javascript
jQuery实现的数值范围range2dslider选取插件特效多款代码分享
2015/08/27 Javascript
js为什么不能正确处理小数运算?
2015/12/29 Javascript
简单解析JavaScript中的__proto__属性
2016/05/10 Javascript
全面解析Bootstrap中scrollspy(滚动监听)的使用方法
2016/06/06 Javascript
vue组件父子间通信之综合练习(聊天室)
2017/11/07 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
bootstrap table支持高度百分比的实例代码
2018/02/28 Javascript
解决vue 绑定对象内点击事件失效问题
2018/09/05 Javascript
vue下拉菜单组件(含搜索)的实现代码
2018/11/25 Javascript
详解如何探测小程序返回到webview页面
2019/05/14 Javascript
vue ssr+koa2构建服务端渲染的示例代码
2020/03/23 Javascript
区分vue-router的hash和history模式
2020/10/03 Javascript
使用Python来做一个屏幕录制工具的操作代码
2020/01/18 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
Python调用shell cmd方法代码示例解析
2020/06/18 Python
Python打印不合法的文件名
2020/07/31 Python
html5文字阴影效果text-shadow使用示例
2013/07/25 HTML / CSS
HTML5 常见面试题之PC端和移动端区别介绍
2018/01/22 HTML / CSS
使用SVG实现提示框功能的示例代码
2020/06/05 HTML / CSS
韩国商务邀请函
2014/01/14 职场文书
初中三年毕业生的自我评价分享
2014/02/14 职场文书
物流专员岗位职责
2014/02/17 职场文书
党员个人批评与自我批评
2014/10/14 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
新手必备Python开发环境搭建教程
2021/05/28 Python
详解gantt甘特图可拖拽、编辑(vue、react都可用 highcharts)
2021/11/27 Vue.js
vue中使用mockjs配置和使用方式
2022/04/06 Vue.js
MySQL创建管理HASH分区
2022/04/13 MySQL