Django’da signals kullanımı

Django’da signals kullanımı
Django’nun admin paneli çoğu durum için yeterli olsa da biraz değişik bir şey yapmak istediğinizde tutorial’da bahsedilenden farklı bir işlem yapmanız gerekiyor. Sinyaller (signals), Django’nun bu durumda yardımcı olabilecek bir özelliği.

Sinyaller, uygulamada belirlenen alıcıların göndericilerin yaptığı işlemlerden haberdar olmasını sağlar. Bu ne demek biraz açalım; mesela bir modeliniz var ve bu model save edildiği zaman başka bir fonksiyon çağırmak istiyorsunuz. Modelinizi gönderici (sender) olarak belirleyip olurturduğunuz diğer bir fonksiyonu da alıcı (receiver) olarak gösterebilirsiniz.

Django’da kendiniz sinyal fonksiyonlarınızı oluşturabileceğiniz gibi hazırda bulunan sinyaller de mevcut. Modellerin kaydedilme esnasında (öncesinde ve sonrasında) tetiklenen sinyaller ve http isteği başlarken ve biterken tetiklenen sinyaller gibi.

Bir örnek vermek gerekirse:

Ekipman isimli bir modelimiz olsun. Bu modelde her değişiklik yapıldığında bunu ayrı bir tabloda tutmak istiyoruz. Böylelikle ekipmanda yapılan her değişikliği kayıt altında tutabileceğiz.

class Ekipman(models.Model):
    seri_no = models.CharField(max_length=20)
    bulundugu_yer = models.CharField(max_length=20)
    tamirde = models.BooleanField()
    notlar = models.TextField(blank=True)

Gecmis isimli bir de tablomuz var. Buna da yapılan değişiklikleri kaydedeceğiz.

class Gecmis(models.Model):
    ekipman = models.ForeignKey(Ekipman)
    seri_no = models.CharField(max_length=20)
    bulundugu_yer = models.CharField(max_length=20)
    tamirde = models.BooleanField()
    notlar = models.TextField(blank=True)

Şimdi de kayıt işlemini gerçekleştirecek fonksiyonumuzu oluşturalım.

def GecmisTut(sender, **kwargs):
    ekipman = kwargs['instance']
    gecmis = Gecmis(ekipman = ekipman, \
    seri_no = ekipman.seri_no, \
    bulundugu_yer = ekipman.bulundugu_yer, \
    tamirde = ekipman.tamirde, \
    notlar = ekipman.notlar)
 
    ekipman.save()

Alıcı fonksiyonu her zaman sender ve kwargs parametrelerini almalıdır. sender parametresi göndericinin sınıfını (instance’ını değil) tutar. Oluşturduğumuz modelin kendisini (instance’ını) almak için kwargs içindeki instance anahtarını kullanmamız gerekir.

Bu fonksiyonu iki şekilde gönderici ile bağlayabiliriz. Model kaydedildikten sonra alıcının çağırılmasını istediğimize göre:

from django.models.signals import post_save

def GecmisTut(sender, **kwargs):
    ekipman = kwargs['instance']
    gecmis = Gecmis(ekipman = ekipman, \
    seri_no = ekipman.seri_no, \
    bulundugu_yer = ekipman.bulundugu_yer, \
    tamirde = ekipman.tamirde, \
    notlar = ekipman.notlar)
 
    ekipman.save()
 
post_save.connect(GecmisTut, sender=Gecmis)

Veya fonksiyonu bir decorator ile kullanalım:

from django.models.signals import post_save

@receiver(post_save, sender=Ekipman)
def GecmisTut(sender, **kwargs):
    ekipman = kwargs['instance']
    gecmis = Gecmis(ekipman = ekipman, \
    seri_no = ekipman.seri_no, \
    bulundugu_yer = ekipman.bulundugu_yer, \
    tamirde = ekipman.tamirde, \
    notlar = ekipman.notlar)
 
    ekipman.save()

şeklinde kullanabiliriz.