2010-02-22 18 views
6

Ben these proposed signal decorators gibi bir şey yapmaya çalışıyorum. Dekore edilmiş yöntemi bir sinyale bağlayan bir dekoratörün yanı sıra (sinyalin dekoratörün argümanı olarak gönderici ile birlikte), dekoratörü sınıf yöntemleri üzerinde kullanmak isterim.Django Model Üzerinden Dekoratörlü Sinyal mi?

ben şöyle dekoratör kullanmak istiyorum:

class ModelA(Model): 

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

dekoratör: Ben bunu yaptığımda

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 

alıyorum hatadır:

 
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. 

Sorun şu ki, @classmethod, callable olmayan bir sınıf yöntemi nesnesi döndürüyor. Gerçekten başlık altında nasıl classmethod eser anlamıyorum, ama örneğin ModelA.observe_model_b_saved, sınıf erişilir kadar sınıf yöntemi nesne çağrılabilir çevrilmiş olmadığını this reference page dan tahmin. Her iki yöntemde de (1) yöntemimi bir model üzerinde sınıf veya örnek yöntemi olarak tanımlayabilirim ve (2) doğrudan yöntem tanımında bir dekoratör kullanarak bir sinyale bağlayabilir miyim? Teşekkürler!

+0

@classmethod ve @connect? Sı sırasını değiştirirseniz işe yarıyor mu? – Wogan

+0

Hayır şimdi alıyorum: "observe_model_b_saved() tam 4 sigara kelime argümanlar (0 Verilen) alır". Bu ne demek? –

cevap

2

Bu sizin örnek koddan açık değil, bu yüzden sinyal dinleyici aslında @classmethod olmak zorunda olmadığını soran olurdu? Yani Düzenli bir yöntem yapacak (ve daha sonra sınıfa erişmeniz gerekiyorsa self.__class__ kullanın)? Bir yöntem olmak zorunda mıdır (sadece bir işlev kullanabilir misiniz)?

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) 
+0

Teşekkürler Bu sorunun başka bir versiyonuna önerilmiş bir çözümle gideceğim düşünüyorum: sınıf dekoratörler. Sınıf dekoratörü, tüm sınıf yüklendikten sonra sinyal bağlantısını oluşturabilir ve bu, doğrudan sınıf yöntemine erişememe sorununu ortadan kaldırır. http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class –

1

bunu yerine @staticmethod yapabilir misiniz:

Başka bir seçenek sinyali dinlemek ve @classmethod çağrısına temsilci için ikinci yöntemi kullanmak olabilir? Böylece, dekoratörlerin sırasını değiştirebilirsin.

class ModelA(Model): 

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

yerine cls argüman geçti almanın tam adıyla sınıfa başvurmak zorunda kalacak, ancak bu benzer bir kod organizasyon tutmak için izin verecek.

+0

Teşekkür, ama bu çözüm çünkü yöntemlerde benim için işe yaramaz ben Aşırı yüklenebilen üyeleri almak için sınıfa dinamik olarak erişmeye bağlıdır. Örneğin. Üst sınıf, bazı özniteliklere dayanan bir yöntem tanımlar, ancak alt sınıf özniteliği aşırı yükler. Aşırı öznitelik özniteliğine ihtiyacım var ve adından açıkça isimlendirmeden gelen sınıfa değil. –

0

Matt'in cevap kapalı göre, @staticmethod hile benim için çalıştı. Somut olmayan bir modele başvurmak için bir dize kullanabilirsiniz.

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