防止Django 1.4.3中的post_save重复信号
我正在尝试写一些代码,让每当用户修改一个模型对象时,就发送一封邮件。目前,我在努力让models.py中的一个方法接收post_save信号。我知道post_save信号通常会发送两次,因此,解决这个问题的方法是使用dispatch_uid参数。我已经这样做了,但出于某种奇怪的原因,我仍然收到了两个信号。以下是我应用程序的model.py文件中的代码。
from django.db import models
from django.db.models.signals import post_save
def send_email(sender, **kwargs):
print "Signal sent." #just a placeholder
post_save.connect(send_email, dispatch_uid="unique_identifier")
class Library_Associates (models.Model):
first_name = models.CharField(max_length = 200)
last_name = models.CharField(max_length = 200)
department_choices = (
('ENG', 'Engineering'),
('ART', 'Arts and Sciences'),
('AFM', 'Accounting and Financial Managment'),
('MAT', 'Mathematics'),
)
department = models.CharField(max_length = 3, choices = department_choices, default = 'ENG')
pub_date = models.DateTimeField ('date published')
def __unicode__(self):
return self.first_name
class Meta:
verbose_name_plural = 'Library Associates'
class Info_Desk_Staff (models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
salary = models.IntegerField()
hours_worked = models.IntegerField()
def __unicode__(self):
return self.first_name
class Meta:
verbose_name_plural = 'Info Desk Staff'
我已经重启了服务器好几次,重置/删除了应用程序的所有数据,但我仍然收到了两个信号。我的代码是否存在根本性的问题?任何建议或见解都将非常感激!谢谢!
1 个回答
6
你的问题出在每次通过管理界面修改对象时,管理应用会创建一个叫做 django.contrib.admin.models.LogEntry 的实例,这个实例用来记录所做的更改。
因为你在所有对象上都监听了 post_save 事件,所以你的监听器会被调用两次——第一次是针对你的模型,第二次是针对 LogEntry 模型。
可能的解决方案包括:
为每个模型单独注册你的监听器(例如,可以选择你的模型,然后在一个循环中进行注册),使用 sender 参数在 post_save 方法中。
for model in get_models(): post_save.connect(send_email, sender = model, dispatch_uid='unique_identifier')
检查发送给监听器的 sender 是否不是 django.contrib.admin.models.LogEntry 的实例。
from django.contrib.admin.models import LogEntry ... def send_email(sender, **kwargs): if isinstance(sender, LogEntry): return
给你的模型一个共同的父类,并在监听器中使用这个父类进行测试。
class MyModel(models.Model): pass class Library_Associates (MyModel): ... class Info_Desk_Staff (MyModel): ... def send_email(sender, **kwargs): if not isinstance(sender, MyModel): return