Consolidating multiple post_save signals with one receiver

后端 未结 4 916
旧时难觅i
旧时难觅i 2020-12-15 02:37

So I read the Django source code (post 1.5) that you can now register multiple multiple signals to a receiver function:

def receiver(signal, **kwargs):
    \         


        
相关标签:
4条回答
  • 2020-12-15 03:07

    Per the Django documentation on receivers, receivers by default do not need to be connected to a specific sender. So what you're describing is default Django functionality.

    In other words, to do this using the @receiver decorator you simply don't specify a sender in the decorator. For example:

    @receiver(post_save) # instead of @receiver(post_save, sender=Rebel)
    def set_winner(sender, instance=None, created=False, **kwargs):
        list_of_models = ('Rebel', 'Stormtrooper', 'Battleground')
        if sender.__name__ in list_of_models: # this is the dynamic part you want
            if created: # only run when object is first created
                ... set the winner ...
    

    This assumes models that look like:

    class Rebel(models.Model):
        ...
    
    class Stormtrooper(models.Model):
        ...
    
    class Battleground(models.Model):
        ...
    
    0 讨论(0)
  • 2020-12-15 03:09

    You can use that using @receiver decorator:

    @receiver(post_save, sender=Model1)
    @receiver(post_save, sender=Model2)
    @receiver(post_save, sender=Model3)
    def my_signal_handle(sender , **kwargs)
        # some code here
    
    0 讨论(0)
  • 2020-12-15 03:17

    You can skip model_name and you will connect to all models post_save. Then you can filter if you are in right model in the handler:

    post_save.connect(foo)
    
    def foo(sender, **kwargs):
        if sender not in [FooModel, BarModel]:
            return
        ... actual code ...
    

    or you can filter based on field in model:

    def foo(sender, **kwargs):
        if not getattr(sender, 'process_by_foo', False):
            return
        ... actual code ...
    
    0 讨论(0)
  • 2020-12-15 03:17
    def receiver_with_multiple_senders(signal, senders, **kwargs):
        """
        Based on django.dispatch.dispatcher.receiver
    
        Allows multiple senders so we can avoid using a stack of
        regular receiver decorators with one sender each.
        """
    
        def decorator(receiver_func):
            for sender in senders:
                if isinstance(signal, (list, tuple)):
                    for s in signal:
                        s.connect(receiver_func, sender=sender, **kwargs)
                else:
                    signal.connect(receiver_func, sender=sender, **kwargs)
    
            return receiver_func
    
        return decorator
    
    0 讨论(0)
提交回复
热议问题