8
votes

Django Signal via décorateur sur la méthode du modèle?

J'essaie de faire quelque chose comme ces décorateurs de signaux proposés . En plus d'avoir un décorateur qui relie la méthode décorée à un signal (avec l'expéditeur du signal comme argument du décorateur), j'aimerais utiliser le décorateur sur des méthodes de classe.

J'aimerais utiliser le décorateur comme Donc: p> xxx pré>

le décorateur est: p> xxx pré>

L'erreur que je reçois quand je le fais est: p>

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.


2 commentaires

Est-ce que cela fonctionne si vous échangez l'ordre de @ClassMethod et @Connect?


Non maintenant, je reçois: "Observer_model_b_saved () prend exactement 4 arguments non clés (0 donné)". Qu'est-ce que ça veut dire?


3 Réponses :


2
votes

Ce n'est pas clair de votre code exemple, je vous demanderais donc si l'auditeur de signal doit être un @classmethod ? C'est à dire. Une méthode régulière sera-t-elle (puis d'utiliser auto .__ classe __ si vous avez toujours besoin d'accéder à la classe elle-même)? Cela doit-il être une méthode du tout (pouvez-vous simplement utiliser une fonction)?

Une autre option peut être d'utiliser une deuxième méthode pour écouter le signal et déléguer l'appel au @classmethod : xxx


1 commentaires

Merci je pense que je vais aller avec une solution que quelqu'un a suggéré une autre version de cette question: décorateurs de classe. Le décorateur de classe peut créer la connexion de signal après la charge de la classe entière et cela évite le problème de ne pas pouvoir accéder directement à la méthode de la classe. Stackoverflow.com/Questtions/2366713/...



3
votes

Pourriez-vous en faire un @StaticMethod à la place? De cette façon, vous pouvez simplement échanger l'ordre des décorateurs.

class ModelA(Model):

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


1 commentaires

Merci, mais cette solution ne fonctionnera pas pour moi car dans les méthodes que je dépends de l'accès à la classe de manière dynamique afin de récupérer des membres qui ont peut-être été surchargé. Par exemple. La superclasse définit une méthode qui repose sur un attribut, mais la sous-classe surcharge l'attribut. J'ai besoin de l'attribut surchargé et non de celui qui vient de nommer explicitement la classe par nom.



0
votes

Basé sur la réponse de Matt, le tour @StaticMethod a fonctionné pour moi. Vous pouvez utiliser une chaîne pour faire référence à un modèle non concrètement.

class Foo(Model):

    @staticmethod
    @receiver(models.signals.post_save, sender='someappname.Foo')
    def post_save(sender, instance, created, **kwargs):
            print 'IN POST SAVE', sender, instance.id, created


0 commentaires