Django将模型排除在发送信号之外



我想通过处理postrongave、delete和init信号来跟踪我的模型及其CRUD操作,然后将有关所处理操作的条目保存到数据库中。

def handle_model_saved(sender, **kwargs):
  """Trap the signal and do whatever is needed"""
  entry=CRUD_Storage()
  entry.entry='Object "'+sender._meta.module_name+'" was saved.'
  entry.save()

有趣的是,这是一个保存的递归。。。

我创建了模型CRUD_Storage,我想防止它发送诸如pre(post)init、delete、save之类的信号。

我认为你无法阻止Django发送这些信号。

但是,您可以调整处理程序,使其不记录CRUD_Storage模型的保存。

def handle_model_saved(sender, **kwargs):
    """Trap the signal and do whatever is needed"""
    if sender == CRUD_Storage:
        # return early to prevent recursion of saves
        return
    entry=CRUD_Storage()
    entry.entry='Object "'+sender._meta.module_name+'" was saved.'
    entry.save()

这里有一种DRY消除信号的方法。

如果您想消除信号以避免递归,一个简单的方法是在当前实例上设置一个属性,以防止即将到来的信号触发。

这可以使用一个简单的装饰器来完成,该装饰器检查给定实例是否具有'skip_signal'属性,如果是,则阻止调用该方法:

from functools import wraps
def skip_signal():
    def _skip_signal(signal_func):
        @wraps(signal_func)
        def _decorator(sender, instance, **kwargs):
            if hasattr(instance, 'skip_signal'):
                return None
            return signal_func(sender, instance, **kwargs)  
        return _decorator
    return _skip_signal

我们现在可以这样使用它:

from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=MyModel)
@skip_signal()
def my_model_post_save(sender, instance, **kwargs):
    # you processing
    pass
m = MyModel()
# Here we flag the instance with 'skip_signal'
# and my_model_post_save won't be called
# thanks to our decorator, avoiding any signal recursion
m.skip_signal  = True
m.save()

希望这有帮助。

最新更新