我已使用@receiver
装饰器
@receiver(post_save, sender=User, dispatch_uid='ARandomUniqueString')
def do_callback(sender, **kwargs):
我已将from app.signals import *
代码放在__init__.py
中,我可以看到它被导入两次,我认为没有一种好方法可以解决它,可能由于{{1}而发生在installed apps
中。我无法理解为什么尽管只使用settings.py
而dispatch_uid
被调用一次,它仍会运行modelInstance.save
两次。有什么建议吗?
答案 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 docs的dispatch_uid
建议。它不起作用,但我上面粘贴的代码可以工作。