我为我的模型编写了一些智能通用计数器和管理器(以避免select count
查询等)。因此,我为post_save做了一些重要的逻辑。
我想在没有必要时阻止处理信号。 我想完美的界面将是:
instance.save(dispatch_signal=False)
我该如何做到这一点?
更新
有关我正在做什么的更多信息,如果有人感兴趣的话:
希望它足够清楚。请原谅我的语言错误。
答案 0 :(得分:14)
快速而肮脏的解决方案是:
from django.db.models.signals import post_save
from somewhere_in_my_app import my_post_save_handler
post_save.disconnect(my_post_save_handler)
instance.save()
post_save.connect(my_post_save_handler)
但我非常强烈建议您将逻辑移到模型的save()
方法中。
答案 1 :(得分:14)
您可以断开并重新连接信号。尝试在此实用程序类中使用with:
语句:
class SignalBlocker(object):
def __init__(self, signal, receiver, **kwargs):
self.signal = signal
self.receiver = receiver
self.kwargs = kwargs
def __enter__(self, *args, **kwargs):
self.signal.disconnect(self.receiver)
def __exit__(self, *args, **kwargs):
self.signal.connect(self.receiver, **self.kwargs)
您现在可以使用:
with SignalBlocker(post_save, my_post_save_handler):
instance.save()
答案 2 :(得分:12)
我找到了简单易用的解决方案:
MyModel.objects.filter(pk=instance.id).update(**data)
这是由于(https://docs.djangoproject.com/en/1.5/ref/models/querysets/#update):
最后,意识到update()在SQL级别进行更新, 因此,不会在模型上调用任何save()方法,也不会 发出pre_save或post_save信号(这是...的结果 调用Model.save())。
答案 3 :(得分:2)
您也可以致电instance.save_base(raw=True)
并在raw
或pre_save
信号处理程序中检查post_save
参数:
def my_post_save_handler(instance, raw, **kwargs):
if not raw:
heavy_logic()
你可以添加一些糖并获得完美的界面:
class MyModel:
def save(self, dispatch_signal=True, **kwargs):
self.save_base(raw=not dispatch_signal, **kwargs)
请注意,save_base()
不是Django公共API的一部分,因此在将来的版本中可能会更改。