10

@receiver我已经使用装饰器在回调中注册了我的信号

@receiver(post_save, sender=User, dispatch_uid='ARandomUniqueString') 
def do_callback(sender, **kwargs):

我已经把from app.signals import *代码放进去__init__.py,我可以看到它被导入了两次,我认为没有很好的方法来修复它,可能是由于installed appsin settings.py. 我不明白为什么尽管使用dispatch_uid并且modelInstance.save只被调用一次,它仍然运行do_callback两次。有什么建议么?

4

4 回答 4

13

好的,所以我将导入移动到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__(...)and .save()

结论

dispatch_uid确实有效,并且进行单一导入仍然是一个好习惯。

于 2012-08-17T21:12:45.500 回答
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
于 2013-04-23T12:56:37.700 回答
3

我刚刚遇到了同样的问题。我有一个接收器,它做一些重要的事情,在 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的建议。它没有用,但我上面粘贴的代码有效。

于 2017-06-01T21:27:52.937 回答
1

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

你不应该在你的__init__.py文件中放任何东西。

如果您从 中删除它__init__.py,并将其添加到您的底部models.py,它应该可以解决您的问题。

您还应该避免“盲目”进口from foo import *

于 2012-08-17T20:57:58.913 回答