Django Signal via Decorator on Model Method?

decorator, django, django-models, django-signals, python

Solution

Could you make it a @staticmethod instead? That way, you can just swap the order of the decorators.

class ModelA(Model):

    @staticmethod
    @connect.post_save(ModelB)
    def observe_model_b_saved(sender, instance, created, **kwargs):
        # do some stuff
        pass

You'd have to refer to the class by full name instead of getting passed the cls argument, but this would allow you to keep a similar code organization.

Problem

I'm trying to do something like these proposed signal decorators. In addition to having a decorator that connects the decorated method to a signal (with the signal's sender as an argument to the decorator), I would like to use the decorator on class methods. I'd like to use the decorator like so: ``` class ModelA(Model): @connect.post_save(ModelB) @classmethod def observe_model_b_saved(cls, sender, instance, created, **kwargs): # do some stuff pass ``` The decorator is: ``` from django.db.models import signals def post_save(sender): def decorator(view): signals.post_save.connect(sender=sender, receiver=view) return view return decorator ``` The error I get when I do this is: ``` File "/Library/Python/2.6/site-packages//lib/python2.6/site-packages/django/dispatch/dispatcher.py", line 78, in connect AssertionError: Signal receivers must be callable. ``` I guess the problem is that `@classmethod` returns a class method object which is not callable. I don't really understand how `classmethod` works under the hood, but I surmise from this reference page that the class method object is not translated into a callable until it is accessed from the class, e.g., `ModelA.observe_model_b_saved`. Is there any way that I can both (1) define my method as a class or instance method on a model, and (2) connect it to a signal using a decorator directly on the method definition? Thanks!

Original source

Related problems