Herkese merhabalar. Django modellerimizi oluşturur iken bazen birden fazla modelde aynı bilgileri tutmamız gerekebiliyor. Bu da bizi kod tekrarına götürebiliyor. Fakat Django bu problemin önüne geçmek için bize şanslıyız ki Abstract base (soyut temel) modelleri sunuyor.
Abstract Modeller.
Abstract modeller dokümantasyonda da belirtildiği üzere birden fazla modelde aynı bilgileri tutacağınız durumlarda kullanılmak için var.
Herhangi bir Django modelinin yazımından bir farkı yok. Sadece Meta sınıfına geçeceğiniz bir abstract=True parametresi ile bir modeli soyutlayabiliriz.
Bir model soyut olarak tanımlandığında model için veritabanı tablosu, model manager gibi varsayılan model özelliklerine sahip olmaz. Ayrıca direkt olarak örneklenerek nesne oluşturulup kaydedilemez.
Bu kullanımı örnekleyecek olur isek. Elimizde Post ve Comment adlı 2 modelimiz olsun. Bu 2 modelde ortak olarak tutmak isteyebileceğimiz bir çok bilgi bulunacaktır. Örneğin oluşturulma ve güncellenme zamanları veya bir içerik alanı.
İlk olarak ortak alanları tutacak bir abstract model tanımlamamız gerekmekte.
class CommonField(models.Model): content = models.TextField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: abstract = True
Daha sonra tek yapmamız gereken bu alanları barındıracak modellerde bu sınıfı miras almak.
class Post(CommonField): owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) class Comment(CommonField): post = models.ForeignKey(to=Post, on_delete=models.CASCADE)
Basit değil mi?
Meta sınıfında abstract=True dışında yapmış olduğunuz işlemler var ise oluşturacağınız yeni modelde miras alınan sınıfın Meta sınıfını miras alıp değişikliklerinizi yapabilirsiniz.
class Comment(CommonField): .... class Meta(CommonField.Meta): #other settings
Bu arada miras alarak oluşturduğunuz yeni sınıfta abstract=False tanımlaması yapmanız gerekmemekte. Django sizin için aksi belirtilmediği sürece miras alınarak oluşturulan sınıflarda bu tanımlamayı False olarak ayarlamakta.
Ayrıca abstract modelde tanımlamış olduğunuz alanları miras alınarak oluşturulan modellerde yeniden tanımlayabilir veya None a eşitleyerek kullanılmamasını da sağlayabilirsiniz.
class CommonField(models.Model): content = models.TextField() header = models.CharField(max_length=100) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: abstract = True class Post(CommonField): owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) header = models.CharField(max_length=255) class Comment(CommonField): post = models.ForeignKey(to=Post, on_delete=models.CASCADE)
Örneği bu hale getirecek olursak post ve comment nesneleri içinde header bilgisi tutulur fakat 2 farklı maksimum uzunluk validasyonu ile. Pekala comment modelinde header=None diyerek bu alanı yoksayadabiliriz.
Migration dosyalarını oluşturduğunuzda sadece 2 modelin oluşturulduğunu ve bunların işlendiğini görebilirsiniz.
Not olarak eğer abstract modelleriniz ilişkisel alanlar içerecek ise (M2M veya ForeginKey) ve bu alanlarda related_name, related_query_name kullanacak iseniz bunları unique olarak ayarlamanız gerekmekte. Aksi halde Django size hata gösterecektir. İsterseniz bu alanları yeniden tanımlayabilir veya app name, class_name kullanarak bu alanları dinamik ve unique olarak ayarlayabilirsiniz. İlgili link burada.
Son olarak:
Abstract base classlar veya diğer adıyla mixinler yazılan kodun kalitesini önemli ölçüde arttırmakta ve yönetimi kolaylaştırmakta. Birebir aynı işi yapan kodu birden fazla yere kopyala yapıştır yapıyor isek muhtemelen o işi hatalı yapıyoruz 🙂 Düzenli ve mantıklı şekilde kurgulanan bir sistemde çok çok işinize yarayacağına eminim. Görüşmek üzere!
İlk Yorumu Siz Yapın