veritabanı etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
veritabanı etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

20 Ekim 2008 Pazartesi

İlişkisel Alanlar (Relationship Fields)

ForeignKey
Aşağıda foreingkey'in kullanımını anlatmak amacıyla yazılmış ufak bir örnek göreceksiniz.

from django.db import models

class Yazar(models.Model):
isim = models.CharField(max_length=30) #[1]

class Makale(models.Model):
baslik = models.CharField(max_length=100) #[2]
yazar = models.ForeignKey(Yazar) #[3]


[1] Yazar tablosunda CharField veri türünde bir alan oluşturuyoruz.
[2] Makale tablosunda CharField veri türünde bir alan oluşturuyoruz.
[3] Bu alanda ise ForeignKey(Yazar) ifadesi djangoya Makale tablosuna Yazar tablosunun Primary_Key'i ni eklemesini söylüyor. Daha iyi anlaşılması için şöyle örneklendirebiliriz.


Yazar
id--|--isim--|
1 --|Mirat---|
2 --|Gokmen--|
3 --|Deniz---|

Makale
id--|--baslik--|--yazar_id--|
1---|Django----|-----1------|
2---|Python----|-----1------|
3---|PyQt------|-----3------|

Id ile gösterilene alanlar tablomuzun PrimaryKeyleri. Biz eklememiş olmamıza rağmen django otomatik olarak bir PrimaryKey alanı oluşturuyor.
Makale tablosunda ki yazar_id alanı ise bizim Makale sınıfını oluştururken kullandığımız ForeignKey(Yazar) ifadesiyle Makale tablosuna Yazar_id adında bir alan ekliyor ve bu alanlar arasında ilişki kurmamızı sağlıyor. Makale tablosundaki yazar_id alanını yazar tablosundaki id ile eşleştirmemizi sağlıyor.Yani Django ve Python yazılarının sahibi yazar id si 1 olan Mirat'a aitken PyQt yazısı yazar id'si 3 olan bana ait. (Aslında bu konu djangodan çok ilişkisel veri tabanıyla alakalı olduğu için daha ayrıntılı bilgi için google kullanabilirsiniz ;) )

Şimdi djangoyu ilgilendiren kısımlarına gelelim.

Eğer ForeignKey'imiz başka bir uygulamadan çağırılacaksa uygulama ismiyle beraber belirtmemiz gerekiyor. (Django 1.0 dan önceki versiyonlarda bu özelliği kullanamıyorsunuz)


class ornek(models.Model)
yazar = model.ForeignKey('uygulama.tabloadi')


ManyToManyField
Yukarıda foreignkey ile onetomany bir ilişkinin nasıl sağlanacağını gördük. Fakat bazı durumlar vardır ki One-to-Many ile işin içinden çıkamayız. Az önceki örneğimizi biraz değiştirelim ve kitap bilgilerini ve yazarlarını tutan bir uygulama haline çevirelim. İlk örneğimizde bir yazar (one) bir kaç makale(many) yazabiliyordu. Yani makale tablosunda aynı yazar id'sinden birden çok(many) bulunabiliyordu. Peki ya bir kitabın birden çok yazarı olduğu durumlarda ne yapacağız ? Bu gibi durumlarda manytomany ilişkilerini kullabiliriz.


from django.db import models

class Yazar(models.Model):
isim = models.CharField(max_length=30)

class Kitap(models.Model):
baslik = models.CharField(max_length=100)
yazar = models.ManyToMany(Yazar)


Böyle bir ifadeyle django bu manytomany türü ilişkiyi sağlayabilmek için ayrı bir tablo oluşturuyor ve gerekli olan ilişkileri kendisi kuruyor. Bu tablo genelde iki tablonun isimlerinin birleştirilmesiyle oluşuyor. Yani bizim örneğimizde yazar_kitap şeklinde bir tablo oluşturup içerisine yazar_id ve kitap_id alanlarını ekleyip gerekli olan ilişkileri kendisi sağlıyor. Yani yukarıda ki kod veritabanımıza şu şekilde yansıyor.

Yazar
id--|--isim--|
1 --|Mirat---|
2 --|Gokmen--|
3 --|Deniz---|

Kitap
id--|--baslik--|
1---|Django----|
2---|Python----|
3---|PyQt------|

yazarkitap
id--|--yazar_id--|--kitap_id--|
1---|----1------|-----1------|
2---|----1------|-----2------|
3---|----2------|-----3------|
4---|----3------|-----1------|

Şimdi bizden Django kitabının yazarları istediğinde kitap tablosundan 1'idsini alıp yazar kitap tablosundan karşılık gelen yazar idlerini alıyoruz(1 ve 3)
yazar tablosundan da o id'ye karşılık gelen değerleri öğreniyoruz.(Mirat ve Deniz).

İşte manytomany böyle birşey. Olabildiğince basitleştirmeye çalıştım. Eğer hala mantığı tam olarak anlayamadıysanız tek bir cümleyi aklınızdan çıkarmayın. "Eğer bir değer 2 tabloda da birden çok kez yer alıyorsa manytomany kullanmalısınız"

Manytomany ve diğer veritabanı incelikleriyle ilgili anlatılacak çok şey var ama şimdilik burda kesiyorum. Ayrıntılı bilgi için kaynaklar bölümündeki adresleri ziyaret edebilirsiniz. Fırsatım oldukça yeni yazılarda eklemeyi düşünüyorum.

Kaynaklar: http://docs.djangoproject.com/en/dev/ref/models/fields/
http://www.djangoproject.com/documentation/models/
http://docs.djangoproject.com/en/dev/topics/db/models/

19 Eylül 2008 Cuma

Django Notları - 5 (Veritabanı Kullanımına Genel Bakış)

Artık bir django uygulaması yaratmanın vakti geldi.

python manage.py startapp rehber

Gördüğünüz komut projenizin bulunduğu klasör içerisine "rehber" adlı bir dizin oluşturacak ve dizin yapısını incelerseniz models.py ve views.py dosyalarını görebilirsiniz.

Işık yandı mı?

Kullanıcı sizin sitenize rehber dizini altına girdiğinde (adres çubuğuna www.siteniz.com/rehber yazıp enter tuşuna bastığında) rehber adlı uygulamaya giriş yapmış oluyor. Rehber uygulaması kendi içerisinde sergileme ,veri yönetimi modüllüllerini kısacası rehber uygulamanızda kullanacağınız herşeyi barındırıyor. Böylelikle proje geliştirirken ayrı ayrı geliştirdiğiniz uygulamaları birbirinden bağımsız olarak çalışabiliyorlar. Örneğin daha önce geliştirdiğiniz forum uygulamasını yeni projenize entegre etmek bir klasör kopyalamak ve setting.py içerisine bir satır eklemek kadar kolay oluyor.

Yalnız dikkat etmemiz gereken önemli bir nokta var biz burada uygulama oluştururken keyfi davranmadık. Çünkü Django'da veritabanı modellerinin bir uygulama içerisinde bulundurulması gerekiyor.

Şimdi yarattığımız uygulamayı projeniz içerisine yerleştirmemiz gerekli. settings.py dosyası içeriside INSTALLED_APPS adlı bir tüp (tuple) göreceksiniz. Gördüğünüz gibi projemiz şu anda kullanmayacağımız birkaç uygulama barındırıyor. Bunların başına yorum işareti koyarak (#) iptal edelim ve rehber uygulamamızı tüp içerisinde belirtelim. Yalnız burada dikkat etmemiz gereken birşey var Python da tek elemanlı bir tüp belirtiyorsak elemanımızın yanına bir adet , koymayı unutmamalıyız. Çünkü eğer virgül koymazsak python bunu gruplama işareti olarak algılıyor.

tek_elemanli_tup = ('eleman',)

bizim de INSTALLED_APPS'ımız şı şekilde olacak:

INSTALLED_APPS = (
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.sites',
'mysite.rehber',
)


İlk Modelimiz



Şimdi bir uygulama oluşturmuş ve bunu projemiz içine yerleştirmiş bulunmaktayız. Veritabanı ile oynaşmaya başlayabiliriz. mysite/rehber içerisindeki models.py dosyasını düzenlemek üzere açın. Aşağıdaki hale getirin.

from django.db import models

# Create your models here.

class rehber(models.Model):
firstname = models.CharField(max_length = "20")
surname = models.CharField(max_length = "20")
phone = models.CharField(max_length = "14")


İşte bitti ... models.Model sınıfının mirascısı olarak yarattığımız model; atasından veritabanı ile ilgili bütün mekanizmayı miras alıyor. Bu sebepten (yerel veri tabanına senkronize edildikten sonra) kullanılmaya hazır halde.

Veri modellerimizi veri tabanına senkronize etmeden önce herhangi bir soruna oluşmasına karşı onaylatmamız gerek. Bu işlem zorunlu değil ama yinede yapsanız iyi olur.

mysite $ python manage.py validate
0 errors found.


Tamam herşey güzel gözüküyor kazasız belasız modelimizi oluşturmuşuz.. o zaman hadi veritabanımız ile senkronize edelim.

mysite $ python manage.py syncdb
Loading 'initial_data' fixtures...
No fixtures found.


Bu komut size farklı cevaplar verebilir (ben veri tabanı olarak sqlite3 kullanıyorum.) ama error demiyorsa sorun yok demektir. Veritabanımız, modellerimiz oluşturuldu ve senkronize edildi. Şimdi yapabileceğimiz işlemleri uygulamalı olarak ele alalım. Bunun için etkileşimli kabuğu kullanacağız.

mysite $ python manage.py shell

Bu bize bizim projemizdeki ayarlarımızla yüklenmiş bir kabuk açacaktır.

Kayıt Eklemek ve Güncellemek



In [1]: from mysite.rehber.models import rehber

In [2]: people = rehber(firstname='Mirat',surname='bayrak',phone='123 23 23')

In [3]: people.save()


Gördüğünüz ilk satırda projemiz altındaki rehber uygulaması içerisindeki modellerden rehber modelini import ettik. Daha önce söylediğim gibi bu model tek başına veri tabanı işlemleri için gerekli bütün mekanizmayı içeriyor.

2. satırda bir rehber örneği oluşturduk.

3. satırda kaydettik!!

Kayıtları Listelemek



In [4]: print rehber.objects.all()
[]


rehber.nesnelerinin.hepsi() gibi harika bir cümle yapısıyla veri tabanımızdaki bütün kayıtları getirdik (henüz 1 tane var) fakat birşey eksik sanki? print komutu bize bir Python veri sınıfı olarak gösterdi nesnemizi.. neden oldu bu? çünkü modelimiz kendisini nasıl karakter katarı olarak sergileyeceğini bilmiyor (string presentation).

Modele davranış kazandırmak



Şimdi ctrl+d kombinasyonu ile kabuktan çıkın. Tekrar rehber uygulaması içerisindeki models.py dosyasını açın ve onu şu hale getirin.

class rehber(models.Model):
firstname = models.CharField(maxlength=30)
surname = models.CharField(maxlength=30)
phone = models.CharField(maxlength=14)
def __str__(self):
return "name : %s , surname : %s , phone : %s" % (self.firstname,self.surname,self.phone)


Burada ne yaptık? __str__ fonksiyonu tanımlayarak modelimize kendisini nasıl metin olarak sergileyeceğini öğrettik.

Önemli not : Django 1.0 ile birlikte __str__() yerine __unicode__() fonksiyonunun kullanılması öneriliyor.

Şimdi tekrar kabuğa dönüp kayıtlarımızı listeletmeye çalışalım.

In [1]: from mysite.rehber.models import rehber

In [2]: print rehber.objects.all()

[

Veriyi Güncellemek



Eğer yukarıda geçen kaydetme kısmında verdiğimiz kodda people örneğinin içindeki herhangi bir alanı değiştirip tekrar kaydetseydik. Bu yeni bir kayıt olarak geçmeyecek, veritabanındaki aynı kayıt güncellenecekti.

In [1]: from mysite.rehber.models import rehber

In [2]: people = rehber(firstname='Mirat',surname='Çaylak',phone='123 23 23') # örnek oluştur

In [3]: people.save() # kaydet

In [4]: rehber.objects.all() # bütün veri tabanını getir

Out[4]: []

In [5]: people.surname = "kamil" # örnepğin surname alanını değiştir

In [6]: people.save() # tekrar kaydet

In [7]: rehber.objects.all() # yeni kayıt oluşmadı, olan değiştirildi.

Out[7]: []


Filitrelemek



Sadece belli kriterlere sahip veriyi çekmek istediğimizde ,örneğin sadece firstname alanı "Mirat" olan kayıtları getirmek için...

In [9]: rehber.objects.get(firstname='Mirat')
Out[9]:


"Mi" hecesiyle başlayan kayıtları listelemek için :

>> print Entry.objects.filter(firstname__startswith="Mi")

İçinde "rat" hecesi geçen kayıtları aramak için..

>> print Entry.objects.filter(firstname__contains="rat"),

Sıralamak



Genelde veritabanından çektiğimiz veriyi belli bir sıralamaya göre sergilemek isteriz. Örneğin forumlarda her giriş (entry) tarihsel olarak yeniden eskiye doğru sıralanırlar. Biraz önce veritabanından nasıl veri alacağımızı görmüştük sıralama işlemi ise gayet kolay.

isme göre sıralayarak bütün verileri getir :

>>> rehber.objects.order_by("firstname")

kolay değilmi?

hem filitreleme hemde sıralama uygulamak istediğimizde:

>>> rehber.objects.filter(firstname__contains = "rat").order_by("name")

harika... :) eğer order_by("-name") deseydik sıralamayı tersine çevirecekti.

Parça Almak



Örneğin bütün rehberinizi isim,numara şeklinde değil, sadece numaraları almak istiyorsanız.

>>> rehber.objects.all()[0]

şeklinde o tabloya bir listeymiş gibi davranabilirsiniz.

Bittimi? bitmedi... bir dahaki yazımızda görüşmek üzere...

12 Eylül 2008 Cuma

Django Notları - 4 (Veritabanı Kullanımına Giriş)

Gökmenin yazdığı Django yazılarını takip ettik, artık Django ile dinamik içeriğe sahip web siteleri yapabiliyoruz neşe doluyuz; fakat modern web uygulamalarında çokca veri ile güreş tutmamız gerekmekte. Forum tasarladığınızı düşünün her girdiyi nerede saklayacaksınız text dosyalarda mı? turşu (pickle) kullanarak mı? Bunların arasında arama nasıl yapacaksınız? Bu tip sorunların çözümü verilerinizi veritabanında tutmaktan geçiyor.

Veritabanı nedir?



Bu sorunun cevabını kısaca şöyle cevaplayabiliriz. Bir veritabanı sunucusu sizin için istediğiniz verileri tablolar halinde saklar. Örneğin ,telefon defteriniz isim ve numaraları barındıran şekildeki gibi bir tablo olarak kaydedilebilir. (Türk programcı neden devamlı sözlük ve telefon defteri yapar?)

idİSİMNUMARA
1Ahmet123 12 12
2Dalyan444 16 00
3Hüseyin321 2222
4Kemal555 44 23


Daha sonra veritabanı sunucusuna sql dilinde cümleler gönderir, cevaplar alırız. örneğin, "Adı Hüseyin olan kişinin telon numarası nedir?" diye sorduğumuzda veritabanı sunucusu size 123 12 12 cevabını döndürür. Burada çocuk oyuncağı gibi bahsettiğime bakmayın. Bu konuda yazılmış 2 kiloluk kitaplar bulunuyor. Veritabanı sunucularının genel çalışma mantığına bu kadar değinmemiz yeterli. Daha fazla bilgi için "internet derya deniz, arama yapmayan domuz" diyor konumuza devam ediyorum.

Aptal Yöntem



Php dilinden anlayanlar Django daki veritabanı hizmetini görünce biraz üzülecekler (daha kolay bir yöntemi varmıydı bilmiyorum ama ben gayet sorgu yazıyordum) zira tek satır SQL cümlesi yazmadan bütün verilerinize taklacı güvercin muamelesi yapabiliyor , kaydetme , silme , güncelleme ihtiyaçlarınızı karşılayabiliyorsunuz.

Fakat yinede bilgi vermek, klasik veritabanı kullanımı ile arasındaki farkları gösterebilmek amacıyla biraz önce belirttiğim telefon rehberindeki kayıtları okumaya yarayan kodu veriyorum.

from django.shortcuts import render_to_response # buranın ne olduğunu Gökmen açıklayacak
import MySQLdb

def book_list(request):
db = MySQLdb.connect(user='root',db='mydb',passwd='',host='localhost') # veritabanımıza bağlantı yapıyoruz
cursor = cursor.db.cursor() # bir kürsor oluşturuyoruz.
cursor.execute('SELECT numara FROM rehber WHERE isim = "Hüseyin"') # bir sql cümleciği kuruup sorgu yapıyoruz.
names = [row[0] for row in cursor.fetchall()] # çıkan sonuçları ayrıştırıyoruz.
db.close() # bağlantıyı kapat # veritabanına olan bağlantıyı kapatıyoruz.
return render_to_response('book_list.html',{'names':names}) # yazdırıyoruz.


Böyle bir kodlama yaptıysak karalar bağlayabiliriz çünkü..

  • Veritabanı bağlantısı mysql üzerinden sabit ayarlarla yapıldı (buna hard-coded deniyor) ileride değiştirmek istersek uğraşımız yaman olacak. Hele bir de mysql yerine başka bir veritabanı kullanmaya kalkarsak vay halimize..

  • İşimize yaramayacak birsürü kod yazdık bağlantıyı yaptık kürsör ayarladık bağlantıyı kapattık vesaire..

  • MySQL bilgisine ihtiyaç duyduk. Python'la Django ile zaten toslaşıp duruyorken birde SQL gibi derya deniz bir konuyu öğrenmemiz gerekti.


Django Avantajları



Django uygulama parçacıkları arasında gevşek bağ kurma felsefesi ile çalışıyor. Böylelikle parçalar üzerinde herhangi bir değişiklik yaptığımız zaman uygulamanın geneli bundan ya hiç etkilenmiyor ya da çok az etkileniyor. Örneğin önceki konularda template sistemlerini incelerken programın çalışma mekanizması ile sergilenme aşamasını birbirinden ayırdık. Template'ler değişse bile uygulamanın diğer alanlarına etki etmedi. Django veritabanı ile olan uğraşımız sırasında bize aynı imkanları sunuyor. Örneğin MySQL den PostgreSQL veritabanı motoruna geçişiniz 3 satırlık değişiklik gerektiriyor...

Veritabanını Ayarlamak



Django'nun veritabanı katmanını incelemeye başlayabiliriz. Uygulamamız boyunca kullanacağımız veritabanı ayarlarını settings.py içerisinde belirtiyoruz.

Settings.py dosyasını açtığınız zaman veritabanı ile ilgili şu satırları görürsünüz.
DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''


Zaten yanlarında açıklamaları # işaretinden sonra belirtilmiş fakat ben yinede burada tekrar değineyim.

DATABASE_ENGINE:

Kullanacağınız veritabanı motoru, Django "mysql","postgresql","postgresql_psycopg","sqlite3","oracle" veritabanlarına tam destek vermekte birini seçip yazın.

DATABASE_NAME:

Bir veritabanı sunucusu içinde birden fazla veritabanı barındırır. Kullanacağımız veritabanı ismi buraya gelecek. (veritabanı sunucusu > veritabanı > tablolar)

DATABASE_USER:

Bir veritabanı sunucusunda oturum açmak için kullanıcı adı ve şifreye ihtiyaç duyarsınız.

DATABASE_PASSWORD

acaba nedir nedir?

DATABASE_HOST

Veritabanı sunucunuz Django uygulamanızın çalıştığı sunucu ile aynı makinada çalışıyorsa localhost, değil ise veritabanı sunucunuzun ip adresi olmalıdır. Sqlite3 kullanıyorsanız burayı boş bırakın.

DATABASE_PORT

Boş bırakırsanız öntanımlı porttan bağlanmaya çalışır. Port numarasını girerseniz verdiğiniz port numarasından bağlanmaya çalışır.

Bütün bu ayarları doğru bir şekilde yaptığınızdan emin olmak için terminalde projenizin bulunduğu dizine gidip, python manage.py shellkomutunu verin. Bu sırada bir yanda youtube ile video izlemeye çalıştığınız için karşınıza çikita ajdar gelecek (bana öyle oldu aklım çıkıyordu) kapatın youtube'u.. neyse karşınıza python interaktif kabuğu gelecek fakat Django ile yapılmış ayarlarnız yüklenmiş olacak. Ne demek istediğim aşağıdaki örnekle yeterince kendini belli ediyor zaten.
>> from django.db import connection
>>>cursor = connection.cursor()


Bu komutlar projenizin veritabanı ayarları ile veritabanına django üzerinden bağlantı kurmaya çalışacak. Eğer herhangi bir hata döndürmez ise ayarlarımızı doğru yaptık demektir. Peki biz bu şekilde mi kullanacağız? tabii ki hayır :). Bir dahaki yazımda Django'da veri modelleri ile ilgilenecek ilk uygulamamızı yaratacağız.