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



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

是否有办法阻止Django在特定的save()调用时发送post_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)并将其保存在自己的数据库中。我不想使用任何类型的DB同步,因为应用程序需要易于部署,甚至应该与sqlite一起工作。

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

我通过调用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

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

如果这不是一个选项,你也可以使用一些全局线程本地状态,这将包含主键(和可能的类型)的模型的信号被抑制。

最新更新