阻止特定save()调用的信号发送

时间:2014-05-20 22:00:45

标签: python django django-models django-signals

我在收到post_save信号时会对模型的对象执行一些持久性操作,其中包括对save()的调用。显然,save()调用再次发送post_save信号,并且我正在信号递归中着陆。

有没有办法阻止Django在特定post_save电话上发送save()信号?或者,如果呼叫被“循环”,我可以在我的信号回调中检测到吗?

那不起作用

我尝试通过添加属性来修改模型的对象,但似乎django.db.models.base.Model.save_base将“已清理”的对象传递给信号回调,该回调不再包含该属性:

def callback(sender, **kwargs):
    instance = kwargs['instance']
    if not hasattr(instance, 'no_signal'):
        # (...) Perform actions
        instance.no_signal = True
        instance.save()
post_save.connect(callback, dispatch_uid='post_save_callback')

背景

完整的情况比接收信号,修改对象和持久化更复杂。事实上,我有两个相同的Django实例(在不同的服务器上),它们交换创建或修改的对象(通过ØMQ)并将其保存在自己的数据库中。我不想使用任何类型的数据库同步,因为应用程序需要易于部署,甚至应该使用sqlite。

由于这应该适用于所有模型,无论是通过视图还是管理应用程序修改/创建它们,我都希望找到一种方法来使用post_save信号而不是引入自己的信号,需要在项目的各个点(包括User模型)中触发。

2 个答案:

答案 0 :(得分:4)

我通过调用save_base(raw=True)而不是save()解决了问题,然后检查了信号处理程序中的kwarg['raw']

def receive_signal(sender, **kwargs):
    instance, raw = kwargs['instance'], kwargs['raw']
    if not raw:
        # Send the instance to the other Django node

实际上,我正在使用django.core.serializers.deserialize反序列化我收到的对象,然后对反序列化的对象执行save(),这些对象调用模型的save_base(raw=True)

  

另见:   https://stackoverflow.com/a/22560210/145013

答案 1 :(得分:1)

首先:如果以不进行多线程处理的方式部署django程序(可以进行多处理!),可以随意断开信号,并且不会丢失任何其他线程的信号。

如果这不是一个选项,你也可以使用一些global thread-local state,它将包含信号被抑制的模型的原型键(和可能的类型)。