Skip to content

[DJ13] @receiver decorator must be on top of all the other decorators

Rocio Aramberri edited this page Aug 4, 2022 · 3 revisions

The @receiver decorator is different from other decorators because it doesn't return a wrapped function like normal decorators. Instead, it connects the passed function to the signal and returns it without modification.

This means that all other decorators put on top of @receiver do not affect the function that is already connected to the signal handler.

Example code:

@transaction.atomic
@receiver(post_save, sender=Article)
def foo(*args, **kwargs):
    ...

Is equivalent to doing:

def foo(*args, **kwargs):
    ...

# Note how the `foo` function passed to `post_save` is not going to be atomic.
post_save.connect(foo, sender=Article) # Note, that this call doesn't affect the name foo
foo = transaction.atomic(foo)

Don't

@transaction.atomic
@receiver(post_save, sender=Article)
def foo(*args, **kwargs):
    ...

Do

@receiver(post_save, sender=Article)
@transaction.atomic
def foo(*args, **kwargs):
    ...

Clone this wiki locally