django temporarily disable signals

前端 未结 2 694
情歌与酒
情歌与酒 2021-02-07 07:41

I have a signal callback in django:

@receiver(post_save, sender=MediumCategory)
def update_category_descendants(sender, **kwargs):
    
    def children_for(categ         


        
相关标签:
2条回答
  • 2021-02-07 08:13

    Perhaps I'm wrong, but I think that category.save() is not needed in your code, add() is enough because change is made in descendant but in category.

    Also, to avoid signals you can:

    • Disconnect signal and reconnect.
    • Use update: Descendant.objects.filter( pk = descendant.pk ).update( category = category )
    0 讨论(0)
  • 2021-02-07 08:14

    To disable a signal on your model, a simple way to go is to set an attribute on the current instance to prevent upcoming signals firing.

    This can be done using a simple decorator that checks if the given instance has the 'skip_signal' attribute, and if so prevents the method from being called:

    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
    

    You can now use it this way:

    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):
        instance.some_field = my_value
        # Here we flag the instance with 'skip_signal'
        # and my_model_post_save won't be called again
        # thanks to our decorator, avoiding any signal recursion
        instance.skip_signal  = True
        instance.save()
    

    Hope This helps.

    0 讨论(0)
提交回复
热议问题