教你如何在Django 1.6中正确使用 Signal

简单回答是: 在其他方法无法使用的情况下,才最后考虑使用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的逻辑使用其他帮助程序实现.

您可能感兴趣的文章:

相关文章

使用OpenCV实现视频去抖 整体步骤: 设置输入输出视频 寻找帧...
前言 对中文标题使用余弦相似度算法和编辑距离相似度分析进行...
前言 之前尝试写过一个爬虫,那时对网页请求还不够熟练,用的...
前言 本文使用Python实现了PCA算法,并使用ORL人脸数据集进行...
前言 使用opencv对图像进行操作,要求:(1)定位银行票据的...
天气预报API 功能 从中国天气网抓取数据返回1-7天的天气数据...