Modeller
Modelleme Elixir'in SQLAlchemy'den dolayı üstün olduğu bir nokta. Modelleri oluşturmak iki ORM'de de eşit kolaylıkta fakat SQLAlchemy'nin katmanlı yapısı daha fazla esneklik sunuyor.
Django ORM'de modellerinize yeni metodlar ekleyebilir[1], gerektiğinde bu metodları Python'un property fonksiyonuyla sararak veritabanında saklanmayacak (ama salt-okunur olması gerekmeyen) alanlar oluşturabilirsiniz[2]. Modeller diğer modellerle veya kendi kendileriyle ilişkilendirilebilir[3]. Hazır alanları yeterli bulmazsanız istediğiniz birinden altsınıf oluşturarak yeni bir alan yaratabilirsiniz.
Yukarıda saydıklarımın hepsini Elixir de başarıyor. Elixir ayrıca modellerden altsınıf yaratarak sınıf hiyerarşisi oluşturmanıza olanak tanıyor[4]. Bu sayede çokbiçimli (çok tipli) sorgulama ve düzenleme yapabiliyorsunuz. Hiyerarşik sınıfların veritabanında nasıl saklanacağını da siz belirleyebiliyorsunuz. Elixir'in bir diğer üstünlüğü uyarlanabilir property'leri. Sadece okuyucu/yazıcı fonksiyonları belirlekle kalmıyor veritabanında birincil anahtar belirlemeden, tablo oluşturulduktan sonra çalıştırılacak koda kadar uyarlama yapabiliyorsunuz.
Belki diğerleri kadar önemli olmasa da model nesnelerinin yaratılması süreci iki bileşenin ne kadar Pythonumsu olduğu hakkında fikir veriyor. Django'da model nesnelerimizi
BirModel.objects.create(alan1=u'değer1', alan2=100, alan3=True)
ile yaratırken, Elixir'de sadece modeli örneklemek yeterli;
BirModel(alan1=u'değer1', alan2=100, alan3=True)
Django ORM'de çeşitli işlevler için özelleşmiş alanlar[9] bulunurken, Elixir temel veri tipleri için birer alan sağlayor ve diğerlerini sizin geliştirmenizi bekliyor. Django ORM'in yetenekli alanları güzel olsa da uyarlanabilirlikleri düşük. Ayrıca, her ne kadar Django bir web çatısı olsa da, Elixir'deki gibi Python nesnelerini turşulayabileceğiniz bir alanın olmamasını yadırgıyorum.
İlişkiler
Her iki ORM'de nesneler arası ilişkileri destekliyor. Elixir ilişkileri her iki tarafta da tanımlamamızı istiyor[5], Django ORM'de ise bir modelde tanımlanan ilişkinin karşılığı diğer modelde otomatik oluşturuluyor. Elixir'de birincil anahtarın değişmesi (SQL: ON UPDATE) ve ilişkilendirilmiş modelin silinmesi (SQL: ON DELETE) durumunda ne yapılacağı ayarlanabilirken Django ORM değişiklikleri diğer nesnelere taşırıyor (SQL: CASCADE).
Bir modeli aynı noktadan birden fazla modelle ilişkilendirme için Django ORM'in çok basit bir GenericRelation nesnesi mevcut. Elixir biraz daha uyarlanabilir bir associable plug-in'iyle geliyor. Sonuçta her ikisi de aynı işlevi başarıyla görüyor.
Elixir'i henüz sınırlarına kadar zorlama imkanım olmadı ama Django özellikle ilişkilerle ilgili noktalarda bekleneni yapmayabiliyor. Bu durum bir de nadiren açıklayıcı olan hata mesajlarıyla birleştiğinde sorunların etrafından dolaşmak zor oluyor. Elixir'in sorunu net biçimde ortaya koyan ve üstelik çözüm önerisiyle gelen hata mesajlarıyla ilk karşılaştığımda epey şaşırmıştım. (Hangisi Pythonumsu?)
Sorgulama
Django ORM'de sorgular (genellikle) QuerySet sınıfları olarak dönüyor. Elixir'in arabirimi Python listeleriyle daha fazla benzeşiyor. Django ORM'de veritabanına yazmak (veya silmek) için model nesnelerindeki metodları kullanıyorsunuz. Elixir ise biraz farklı bir yol izleyerek (Django ORM benzeri davranışı mümkün kılsa da) oturum nesnesi kullanarak tüm değişiklikleri bir kerede kaydetmenize olanak sağlıyor. Her iki ORM'de esnek transaction imkanı sağlıyor. Django ORM tam bir web çatısının parçası olduğu için örneğin bir görünümün başarıyla tamamlanması durumunda transaction'ı tamamlayan kısayollar içeriyor.
Elixir nesneleri sorgularken nesne, alan ve Python ifadelerini kullanmanıza olanak tanıyor. Django ORM ise alan adları ve arama fonksiyonlarını birleştiren kendi küçük dilini kullanıyor. Django ORM ile yapılan aramalar genellikle daha az kod içerse de şık (ve Pythonumsu) durmuyor ve karmaşık aramalarda SQL'e düşmek gerekebiliyor[6].
Örneklemek gerekirse Django ORM:
c = Channel.objects.create(name=u'Internet', parent=Channel.objects.get(name=u'Teknoloji')) c.subscribers.add(User.objects.get(username=u'muhuk')) c.description = u'Internet hakkında.' c.save() tech_channels = Channel.objects.filter(parent__description__startswith=u'Tekno')Benzer kod Elixir'de:
c = Channel(name=u'Internet', parent=Channel.query.get_by(name=u'Teknoloji')) c.subscribers.append(User.objects.get_by(username=u'muhuk')) c.description = u'Internet hakkında.' session.flush() tech_channels = Channel.query.filter(Channel.parent.description.startswith(u'Tekno'))Toparlarsak
Django ORM sadece tek thread ile, Elixir ise multi-thread çalışabiliyor ve oturum nesnesini thread'ler arasında paylaşabiliyor. Django'da ise paralel işlem yapabilmek için prosesleri kullanmanız gerekiyor. Ki GIL varken gerçek anlamda paralel işlem yapmanın tek yolu bu. Her iki ORM de koşutzamanlı çalışıyor.
Django içerik yönetimi uygulamalarında başarısı kanıtlanmış bir web çatısı. Tüm bileşenleri uyum içerisinde çalışıyor ve çeşitli kısayollarla birarada bulunmalarından faydalanıyorlar. CMS türü bir uygulamayı Django ile diğer tıklamalı[7] CMS'lerle kıyaslanabilir zamanda ama çok yüksek seviyede özelleştirilebilir olarak geliştirebilirsiniz. Django ORM çok gelişmiş olmasa da çatının uygun olduğu herhangi bir uygulamada sizi yarı yolda bırakmayacaktır.
Elixir ise çok katmanlı ve gelişmiş SQLAlchemy üzerine oturduğu için her aşamada rahat, zevkli ve güçlü bir programlama ortamı sunuyor. Beklenileni yapıyor[8], hata yaptığınızda da anlayacağınız dilden konuşuyor. Çok daha Pythonumsu ve esnek.
Son olarak çok önem verdiğim bir özellikten (ve tasarım kararından) bahsetmek istiyorum; Django ORM'de Unicode veri alanı yok. Tüm metin alanları kendilerini Unicode olarak kaydediyor ve sonucu Python Unicode nesneleri olarak döndürüyor. Bunun, özellikle ASCII konuşmayanlar için, çok önemli bir özellik olduğunu düşünüyorum. En azından PY3K gelene kadar.
1: Custom manager ile sorgu sonuçlarına, sınıf metodları ile model nesnelerine ek özellikler ekleyebilirsiniz.
2: Örneğin kişinin yaşına modelimizden ulaşmak istiyorsak ikinci normal formumuzu bozmadan yaş fonksiyonunu yeni bir property olarak ekleyebiliriz.
3: Örneğin dosya sistemleri gibi hiyerarşik veri yapılarında.
4: Yanılmıyorsam Django'nun yeni sürümünde modelleri altsınıflayabileceğiz.
5: "Explicit is better than implicit."
6: ORM kullandığımızda en son istediğimiz şey.
7: Joomla gibi, Drupal gibi.
8: "There should be one-- and preferably only one --obvious way to do it."
9: Örneğin URL alanı, e-posta alanı, resim dosyalarıyla eşleşen resim alanı...