Django Signal через Декоратора на Образцовом Методе?

Я пытаюсь сделать что-то как эти предложенные декораторы сигнала. В дополнение к наличию декоратора, который подключает украшенный метод к сигналу (с отправителем сигнала как аргумент декоратору), я хотел бы использовать декоратора на методах класса.

Я хотел бы использовать декоратора как так:

class ModelA(Model):

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

Декоратор:

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

Ошибка, которую я получаю, когда я делаю это:

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.

Я предполагаю, что проблема - это @classmethod возвращает объект метода класса, который не является вызываемым. Я действительно не понимаю как classmethod работы под капотом, но я предполагаю с этой ссылочной страницы, что объект метода класса не переводится в вызываемое, пока к этому не получают доступ от класса, например, ModelA.observe_model_b_saved. Есть ли любой способ, которым я могу оба (1) определить мой метод как метод класса или метод экземпляра для модели и (2) подключить его к сигналу с помощью декоратора непосредственно на определении метода?Спасибо!

8
задан Carl G 2 March 2010 в 20:36
поделиться

2 ответа

Это не ясно из вашего примера кода, поэтому я бы спросил, действительно ли слушателем сигнала должен быть @classmethod ? Т.е. Подойдет ли обычный метод (а затем использовать self .__ class __ , если вам все еще нужен доступ к самому классу)? Это вообще должен быть метод (можно ли просто использовать функцию)?

Другой вариант - использовать второй метод для прослушивания сигнала и делегирования вызова @classmethod :

class ModelA(Model): 

    @classmethod 
    def do_observe_model_b_saved(cls, sender, instance, created, **kwargs): 
        # do some stuff 
        pass 

    @connect.post_save(ModelB) 
    def observe_model_b_saved(self, sender, instance, created, **kwargs): 
        self.do_observe_model_b_saved(sender, instance, created, **kwargs)
2
ответ дан 6 December 2019 в 00:06
поделиться

Не могли бы вы вместо этого сделать @staticmethod? Тогда вы сможете просто поменять порядок декораторов.

class ModelA(Model):

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

Вам придется обращаться к классу по полному имени вместо того, чтобы передавать аргумент cls, но это позволит вам сохранить схожую организацию кода.

2
ответ дан 6 December 2019 в 00:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: