Django ORM ve SQLAlchemy üstünde Elixir karşılaştırması

0
muhuk

Django'yu işimde, Elixir'i (bu yazıdaki her Elixir'i Elixir+SQLAlchemy olarak okuyunuz) kendi projemde kullanıyorum. Dört veya beş yıl önce SQLObject ile başlayıp Unicode sorunları nedeniyle bende büyük hayal kırıklığı yaratan ORM macerama bir ay kadar önce FZ'nin önerisi üzerine bir şans daha verdim. Özellikle benim gibi aşırı titiz biri için SQL programlama belli bir karmaşıklıktan sonra işkence olabiliyor. ORM'ler de zamanla gelişmiş ve çok daha stabil hale gelmiş. Karşılaştırmasını yapacağım iki bileşen de yaygın kullanılan iyi projeler. Burada yazacaklarım tamamen benim fikirlerim, eğer hatalarım olursa veya farklı düşünceleriniz varsa lütfen yorum olarak paylaşınız.

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ı...

Görüşler

0
FZ
Eline sağlık! Doğrusu birkaç gün önce irc.freenode.net'te #fazlamesai kanalında yazışırken dile getirdiğim bu talebimin bu kadar hızlı ve güzel şekilde gerçekleşmesini beklemiyordum, çok sevindim :)
0
T-u-N-i-X
Django'yu işte kullandığınızı söylemişsiniz.. Merak ettim, hangi firmada çalışıyorsunuz ve ne yapıyorsunuz Django ile ? Eğer sakıncası yoksa tabii..
0
T-u-N-i-X
"Python'un property metodu ile sarmak" nedir tam olarak bu arada ?

bir de django'da bir modelle bir süre gittikten sonra (örneğin bir ürün ortaya çıkardık ve kullanmaya başladık) modelde değişiklik yapmak istersek bu yapılamıyor.. ancak yeni uygulamalar ekleyip birbiriyle etkileştirmek lazım ki bunda bile modelle oynamak gerekebiliyor.. bunu nasıl aşıyorsunuz ?
0
muhuk
"Python'un property metodu ile sarmak" nedir tam olarak bu arada ?
Türkçem yetersiz kalıyor, kusuruma bakmayınız; bir getter-setter fonksiyon çifti ile nesnelere yeni bir attribute ekleyebilir ve bunu diğer attribute'lar gibi kullanabilirsiniz. (setter seçimlik)
modelde değişiklik yapmak istersek bu yapılamıyor..
Modelde değişiklik yaptığınızda veritabanını baştan oluşturmanız gerekiyor. Veritabanı şemasını değişen modele uyduran ORM'ler de var diye biliyorum ama çok sağlıklı olabileceğine inanmıyorum. Uygulamanın başında iyi planlama yapıp modele baştan karar vermek en iyisi. Model değiştikçe veritabanını silip (geliştirme için SQLite) tekrar oluşturuyorum. Django'nun Fixture dediği turşulanmış (serialized) veriler, veritabanı her oluşturulduğunda otomatik olarak yüklenebiliyor. Tüm işlem 2dk sürmüyor.
0
Betelgeuse
Django'da bu turşulanmış veriler için fixture yaratmayı nedense beceremedim, google da fazla yardımcı olamadı. Mümkünse fixture oluşturma ile ilgili bir kaynak gösterebilir misin?

Model değiştikçe veritabanını silip yeniden yaratmak pratik ama önceden veri girilmiş bir uygulamada iş zorlaşıyor. Ben bu durumda yeni modeli yeni bir veritabı üzerinde yaratıyorum daha sonra pgadminIII programı ile bu yeni model veritabanında nasıl yaratılmış bakıp eski veritabanını da aynı şekle getiriyorum. Biraz zahmetli oluyor ama önceden girilmiş çok veri olduğunda işe yarıyor.
0
hb
Proje dizinin altinda

python manage.py dumpdata APP_NAME > APP_NAME/fixtures/initial_data.json

komutunu calistirmalisiniz. APP_NAME burada verilerini export etmek istediginiz `application`in adi. Export edilen dosya duzgun girintilensin isterseniz de

python manage.py dumpdata --indent=2 APP_NAME > APP_NAME/fixtures/initial_data.json

komutu isinizi gorecektir. Detayli bilgi $urda http://www.djangoproject.com/documentation/django-admin/
0
sleytr
deseb: Django External Schema Evolution Branch
3-4 aydır ürtetim ortamında yani müşterilerimizin ve ziyaretçilerinin kullandığı siteleri geliştirirken kullanıyorum ve işleri gerçekten kolaylaştırıyor.
0
FZ
3 soru:

- Performans açısından durum nedir? Bir kıyaslama mevcut mu? (Hem veri okuma hem de yazma açısından)

- Lazy loading / caching açısından sundukları esneklik açısından kıyaslarsak durum nedir? Karmaşık bir sınıf hiyerarşisi söz konusu olduğunda mesela bir Hibernate (veya NHibernate + Castle ActiveRecords) ile kıyaslandığında nasıl Python'daki bu sistemler?

- Bu soru RoR kıyaslaması yapabilecek olanlara: Yukarıdaki 2 soruyu RoR - Django (Elixir + SQLAlchemy) kıyaslaması olarak sorarsak ne gibi sonuçlar çıkar?
0
muhuk
Performans kıyaslaması yapma imkanım olmadı. Ancak sanırım Django ORM'in ayrı bir bileşen olarak paketlendiği halini almak gerekir kıyaslama için.
- Lazy loading / caching açısından sundukları esneklik açısından kıyaslarsak durum nedir?
Önemli bir konu, yazıyı yazarken aklıma gelmemişti. Bildiğim kadarıyla Django ORM'de sadece ilişkilendirilmiş nesneleri de ana sorguda getiren select_related() var. Elixir ise tahmin edilebileceği gibi çok daha esnek. Sorgu bazlı, alan bazlı çeşit çeşit lazy loading (eager loading diye geçiyor aslında) seçenekleri sunuyor.

İkisinde de gerçek anlamda bir önbellek yok aslında. Django ORM referans başına hatırlıyor, Elixir ise oturum içerisinde belli bir modeli ayrı ayrı çağırdığınızda (değiştirilmemişse) aynı nesneye referansı döndürüyor. (Sorgu ekonomisi yaparken "is" operatörünün doğru çalışmasını sağlıyor)

Django'da (ORM'in bir özelliği değil ama) (turşulanabilir) herhangibir şeyi önbellekleyebiliyorsunuz. (gerçek önbellek, mesela memcache)

0
FZ
Bilgiler için teşekkürler. Performans problemi orta ölçekli uygulamalarda muhtemelen kendini belli etmeyecektir ancak salkım saçak özellik barındıran karmaşık sınıf hiyearşilerine göre oluşturulmuş yüzlerce, binlerce nesne örneğini bir seferde işleyip ona göre web sayfasını oluşturması gereken durumlarda anlaşılacaktır performans dertleri diye düşünüyorum ("o tür işlemlerde sen de git stored procedure kullan kardeşim" diyenleri duyar gibi oldum bir an ;-)
0
sleytr
Bir süre önce Pardus üzerinde geliştirdiğim bir projeyi Ubuntu sunucuya taşıyınca karşılaştığım onlarca "unicode decode error" dan sonra hepsini tek tek düzeltmek yerine sistemi evrenselleştirmenin daha kolay olacağına karar vermiştim. Her ne kadar Django geliştiricileri önermesede, eğer yazdığınız kodun her zaman yönetimi sizde olacak bir sunucuda çalışacağından eminseniz, site-packages dizinine aşağıdaki dosyayı yerleştirerek karakter verilerini başlarına u harfi koyarak (u'Türkçe' gibi) kodlama mecburiyetinden kurtulabilirsiniz:

/usr/lib/python2.5/site-packages/sitecustomize.py


import sys

sys.setdefaultencoding('utf-8')

0
teknikuzman
reDeV Labs sponsorlugunda ilk türkçe görsel python eğitimi henüz yayın beta ama yine faydalı oldugunu düşünüyorum...katkıda bulunmak isteyen bana msj atsın...
Görüş belirtmek için giriş yapın...

İlgili Yazılar

Web Sitesi Performans İyileştirmeleri

muhuk

Yakın zamanda telvee'nin biraz daha hızlı yüklenebilmesi için django_compressor kullanarak ve arkaplan resimlerini düzenleyerek iyileştirmeler yaptım. İşin güzel yanı bunları gerçekleştirirken geliştirme ortamında veya tasarımda köklü değişiklikler yapmamın gerekmemesiydi. Detaylardan aşağıda bahsedeceğim. Daha önce konunun teorik kısmına kısaca değinmek istiyorum.

IronPython: .Net üzerinde Python - Bölüm - 3

zekzekus

IronPython: dot Net üzerinde Python - 1
IronPython: dot Net üzerinde Python - 2
Yazının özgün haline bu adresten ulaşabilirsiniz.

IronPython içinde bir sınıf oluşturup bunu "System.Object" sınıfından türettiğinizde, IronPython .NET sistemine bir çağrı yapar ve dinamik olarak yeni bir CLR sınıfı oluşturur. IronPython sınıfınıza bir isim atar ve sınıfı kendi "IronPython.NetTypes.System" sınıfına yerleştirir. (Tabii ki Beta versiyon üzerinde çalıştığımızı gözününde bulundurmalısınız. IronPython'ı geliştirenler bu isimuzayı adlarını değiştirebilirler.) Sanırım Poe "Rüya içinde Rüya" gibi bir şeyler yazmıştı. Bu durumda bizde .NET içinde .NET uyguluyoruz. Ya da öyle bir şey işte.

Python, Google'ın da desteği ile ilerlemeye devam ediyor

FZ

Google'ın Python programlama diline olan ilgisi dikkat çekmeye devam ediyor. Eğer SOA (Service Oriented Architecture) tarzı uygulamalar için hızlı prototip geliştirmek istiyorsanız istediğiniz işlevselliği büyük ihtimalle Python 3.0'da bulacaksınız.

Django Girls etkinliklerinden öğrendiklerimiz

elifkus

Kodlama saati yazısını görünce ben de Django Girls’ü ve İstanbul’daki etkinliklerimizden ve öğrendiklerimizden bahsedeyim dedim.

Amerika’da ve Dünya’da yazılımcıların kadın oranını arttırmak için birçok organizasyon ve etkinlik var. Django Girls, bunlardan biri. Ola Sitarska and Ola Sendecka adında iki Polonyalı kadın yazılımcı tarafından başlatılmış, 1 veya 2 günlük bir programlama etkinliği....

PISI Geliştirme Deposu

exa

PISI'nın yeniden canlandırılan geliştirilme dalına ait kaynak kodunu github'da bulabilirsiniz. Kaynakların şu andaki revizyonu 1.1_beta12'dir. Bu revizyonu yerel subversion çalışma kopyalarımdan yükledim, Pardus projesindeki en son idare ettiğim geliştirme dalı deposuna aittir. Dalla ilgili bilgileri aşağıda kendiniz görebilirsiniz.

$ svn info . Path: . Working Copy Root Path:...