尽管uid,Django发布保存信号被调用两次

时间:2012-08-17 20:41:21

标签: python mysql django signals

我已使用@receiver装饰器

在回调中注册了我的信号
@receiver(post_save, sender=User, dispatch_uid='ARandomUniqueString') 
def do_callback(sender, **kwargs):

我已将from app.signals import *代码放在__init__.py中,我可以看到它被导入两次,我认为没有一种好方法可以解决它,可能由于{{1}而发生在installed apps中。我无法理解为什么尽管只使用settings.pydispatch_uid被调用一次,它仍会运行modelInstance.save两次。有什么建议吗?

4 个答案:

答案 0 :(得分:10)

好的,所以我将导入内容移至views.py(或models.py,虽然它只导入了一次,但却被调用了两次。

问题是在创建和保存对象时调用post_save信号。我不知道为什么这样我添加了一个现在有效的解决方法

created = False

    #Workaround to signal being emitted twice on create and save
    if 'created' in kwargs:
        if kwargs['created']:
            created=True

    #If signal is from object creation, return
    if created:
        return

编辑:

post_save被调用两次,因为我使用的.create(...)相当于__init__(...).save()

<强>结论

dispatch_uid确实有效并且进行单次导入仍然是一种很好的做法。

答案 1 :(得分:3)

我在post_save和post_delete信号方面遇到了同样的问题。尽管设置了dispatch_uid,似乎保存了会话对象和LogEntry对象以及创建多个信号。

对我有用的是:

from django.contrib.admin.models import LogEntry
from django.contrib.sessions.models import Session

....

if sender in [LogEntry, Session]:
    return 
else:
    # do your thing here

答案 2 :(得分:1)

  

我已将from app.signals import *代码放在__init__.py

您不应在__init__.py文件中添加任何内容。

如果您从__init__.py中移除此内容,并将其添加到models.py的底部,则可以解决您的问题。

您还应避免“盲目”导入from foo import *

答案 3 :(得分:1)

我刚遇到同样的问题。我有一个接收器,它做了一些重要的事情,每次在Django中创建一个模型实例时必须只做一次。所以,我使用了post_save信号,但是为了创建每个新模型实例而被调用了两次,我正在做Profile.objects.create(...)。 此问题的解决方案是created附带的kwargs标记。以下是如何使用该标志来确保您的预期操作只采取一次:

@receiver(post_save, sender=Profile)
def publish_auction(sender, **kwargs):
    if kwargs['created']:
        kwargs['instance'].send_email_confirmation()

我尝试了Django docsdispatch_uid建议。它不起作用,但我上面粘贴的代码可以工作。