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

18 Haziran 2011 Cumartesi

Python Geliştirme Ortamları

--- Bu yazı yeni başlamayı düşünenler içindir ---

Python'a yeni başlıyorum ve windows ortamında geliştirmek istiyorum bana development ortamı için yapmam gerekenleri ve yararlı toollar önerebilir misiniz?

Windows'ta Geliştirme Yapmak


Windows Dert Ortamı

Açıkcası bu soruyu cevaplarken biraz kurgu yaparak konuşacağım zira Windows ortamında pek geliştirme yapmadım. Yaptığım sırada ise yaptığım sadece daha önce geliştirdiğim bir aleti Windows'a port etmeye çalışmaktan ibaretti. Python'un kurulması, bağımlılıkların yerleştirilmesi ve geliştirmeye başlamadan önce gerekli ayarların yapılması hepsi benim için birer çileye dönüştü. Daha sonrasında ise Dos komut isteminde çalışmak, gerektiğinde ssh ile uzak makineye bağlanmak çilenin noktası oldu benim için. Bilmiyorum belki Linux ortamlarına alıştığım içindir ama gerçekten zordu. / Bu konuda yorumlarınızı bekliyorum.

Eğer Bugün Windows Üzerinde Geliştirme Yapacak Olsam;

Bağımlılık kurma meselesini pip Kullanarak çözmeye çalışırdım. Bir kere kurduktan sonra kendisi Python paketleri için kolay bir bağımlılık kurma aracı olarak çalışıyor. Terminalde ya da Dos ortamında,

pip install hede

Diyerek hede pakedinin kurulmasını sağlayabiliyorsunuz. Ancak bazı modüller pip ile uyumsuzlar. Örneğin geçen gün imaj görüntüleme ve düzenleme pakedi olan PIL'i kurmaya çalıştığım zaman çalışmadığını gördüm. Baya bir uğraştan sonra pip kullanırken PIL pakedini direkt olarak kurmamamız gerektiğini, onun yerine Pillow adlı PIL pakedinin uysallaştırılmış bir versiyonunu kurmak gerektiğini öğrendim.

Bunun dışında bazı paketleri yüklerken başka dillerden kütüphaneler derlenip kurulmaya çalışılıyor bu yüzden sistemde GCC'nin kurulu olması gerekli.

Neyse sözü uzatmayayım,

Siz En iyisi Linux Kullanın


Her zaman söylenir, developer olmaya niyetlenmiş kişinin linux kullanması daha iyidir diye. Sebebi basit, ihtiyacınız olan olabilecek bütün tool'lar kütüphaneler sisteme kurulu olarak gelir. Olmayanları da paket yöneticiniz ile kurar geçersiniz. Dos ekranında komut vermektense bir Linux terminalinde komut vermek her zaman daha kolay ve sağlıklıdır.

Linux ortamında geliştirmeye başlamak için size gerekli olan tek şey kendinize bir ide ya da editor seçip çalışmaya başlamanızdır. Linux camiasının iki kallavi editörü var, bunlardan biri emacs, diğeri ise vim. İkisi de çok güçlü araçlar. İkisi için de eklenti geliştiren binlerce insan vardır sanırım. Ancak söz konusu dil Python ise ben PyCharm'ı tek geçerim. İndirip kullanın, hiç bir kısıtlama yok. Sadece deneme süresi geçtikten sonra kendisini yarım saatte bir kapatıyor. Bence iyi bile sayılabilir böyle olması zira ben bazen bilgisayarın başından kalkmayı unutuyorum.

Sanırım soruya cevap vermiş oldum. Bir daha ki yazıda görüşmek üzere esenkalın.

5 Kasım 2009 Perşembe

Appengine'de Mail Api'nin Kullanılışı

Web sayfanızda iletişim bölümünde hazırladığınız bir form olsun ve sonuçlarını mail adresine gelmesini istiyorsunuz o zaman bu yazı size faydalı olabilir. Sıralama şu şekilde, 1.Formunuzu oluşturun, 2.Veritabanı için modelinizi yazın, 3.Formdan geleni işleyin. Öncelikle dosya yapımız;

|----- app.yaml
|----- iletisim.py
|----- model.py
|----- templates
|----------iletisim.html

Şeklindedir. Sıra sıra gitmek istiyorum. Html formumuzu oluşturalım(template/iletisim.html);



*

*



İsim ve soyisim girişi yapıldığında ve "Yolla" tıklandığında bilgilerin mail adresinize gelmesi için bir kaç adım var. Öncelikle modelimizi oluşturan python kodumuzu yazalım ("model.py")


from google.appengine.ext import webapp,db

class Basvuru_(db.Model):
"""
Basvuru yapilacagi zaman kullanilacak olan model
"""
ad = db.StringProperty(verbose_name="ad",required=True)
soyad = db.StringProperty(verbose_name="soyad",required=True)

##Otamatik Form Olusturmasi icin Kullanabilirsiniz
class Basvuru_form(djangoforms.ModelForm):
#Kullanisi
class Meta:
model = Basvuru_
fields = ('ad','soyad')


Modelimizi de olusturduktan sonra formdan gelen veriyi islemeye geldi. Bunun icin iletisim.py python dosyamızı oluşturup işlemlerimizi yapıyoruz.


from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users,mail
from django.shortcuts import render_to_response
import os,sys

class Iletisim(webapp.RequestHandler):
def get(self):

template_values={}
path = os.path.join(os.path.dirname(__file__), 'templates/iletisim.html')
self.response.out.write(template.render(path, template_values))

def post(self):
veri = Basvuru_form() #Bos girilip girilmedigini kontrol eder
if not veri.is_valid():
ad = up(unicode(self.request.POST["ad"]).encode("utf-8"))
soyad = up(unicode(self.request.POST["soyad"]).encode("utf-8"))
#TURKCE YAP
if ad and soyad: # isim ve soyisim girilmemisse formu kaydetmez
kayit = Basvuru_(ad=ad,soyad=soyad)
kayit.put()

if not mail.is_email_valid(ad): #eger isim yazmamissa size mail atmaz
pass
else:
sender_address = "yetis.m@gmail.com"
yollanan_adres="yetis.m@gmail.com,bilgi@spssanaliz.net"
subject = "Birisi Formu Doldurdu"
body ="\nAd Soyad : "+ad+" "+soyad+"formunuzu doldurdu."
mail.send_mail(sender_address,yollanan_adres, subject, body)
self.redirect("/ulasildi")#Burada form yollama basarili oldugunu gösteren bir mesaj verdirebilirsiniz.
else:
self.response.out.write("Bilgileri eksik girdiniz lütfen tekrar deneyiniz!!!iletisim")
else:
self.redirect("/hata")
application = webapp.WSGIApplication(
[
('/iletisim',Iletisim),
], debug=True)


Bunlara ek olarak dikkatinizi çekmiştir. "up" fonksiyonu kullanılmış, Türkçe karakter sorununu kaldırmak üzere bir arkadaşımdan bulduğum fonksiyonu kullanabilirsiniz. İşinizi oldukça göreceğini düşünüyorum ki sadece python'da değil, hangi dilde olursa olsun bu mantık ile Türkçe karakter problemlerini ortadan kaldırabilirsiniz. Eğer Türkçe karakter (ı,ğ,ü,ş,İ,ö,ç vb..)girilmiş ise büyük harfe çevip bu karakterlerden arındırıyor. Fonksiyonumuz;


def up(text):
"""Girilen TR karakterleri EN karakterlere cevirir"""
groupone = ["a", "b", "c", "\xc3\xa7", "\xc3\x87", "d", "e", "f", "g", \
"\xc4\x9f", "\xc4\x9e", "h", "\xc4\xb1", "i", "\xc4\xb0", \
"j", "k", "l", "m", "n", "o", "\xc3\xb6", "\xc3\x96", "p", \
"q", "r", "s", "\xc5\x9f", "\xc5\x9e", "t", "u", "\xc3\xbc", \
"\xc3\x9c", "v", "w", "x", "y", "z",\
"\xfe","\xde","\xfd","\xdd","\xf0","\xd0","\xfc","\xdc","\xf6","\xd6","\xe7","\xc7",\
"\u015f"]

grouptwo = ["A", "B", "C", "C", "C", "D", "E", "F", "G", "G", "G", "H", \
"I", "I", "I", "J", "K", "L", "M", "N", "O", "O", "O", "P", \
"Q", "R", "S", "S", "S", "T", "U", "U", "U", "V", "W", "X", \
"Y", "Z",\
"S","S","I","I","G","G","U","U","O","O","C","C",\
"S"]
for counter in range(len(groupone)):
text = text.replace(groupone[counter], grouptwo[counter])
return text


Uzun zamandır blogumuzda yazı göremiyorum. Eskiden zevkle okuyordum. Bu yazı benim 20 dakikamı aldı. Özellikle uzak sunucu işlemleri için yazıları çok merak ediyorum ve jquery,ajax,python üclüsünü kullanacak örneklerde sizlerden beklemekteyim.

19 Mart 2009 Perşembe

PyGame İle İlerleme Çubuğu (ProgressBar) Yapalım

Bugün pygame ile basit bir ilerleme çubuğu yapacağız. Uzun zaman alan işlemlerde kullanıcı sıkılmasın diye ekranda sürekli ilerleyen bir çubuk görmeye alışkınsanız bunu neden biz de yapamayalım diyor olabilirsiniz. Öyleyse bu yazı size göre.

İlerleme çubuğu sınıfımız ProgressBar olacak. Bu sınıf görsel hazırlıklarını, miras aldığı ProgressImage'a yaptıracak. Kullanım için biraz ilkel olsa da başlangıç olarak basit bir yöntem seçtim. Ama bu yazının amacı sizlere pygame'i anlatmak. Kullanmanızı ve neden ben de yapmayayım demenizi sağlamak. Bu yüzden kullanılabilirlik konusunda yeterinden öte ayrıntıya girmedim.

Örneğin uzun zaman alan bir döngünüz var:

for i in range(kere):
oturanboga.konus()



Bu döngüde ProgressBar sınıfından bir nesneyi şu şekilde kullanacaksınız:

bariscubugu = ProgressBar(kere, adim, cubukboyutu, ilkrenk, sonrenk)
while not bariscubugu.isEnd():
oturanboga.konus()
bariscubugu.makestep()


Bu kadarı bile sizleri harekete geçirmiştir sanırım. Şimdi yapıma geçelim :)

Önce meşhur modülümüzü import edelim ve bakalım internetten indirmiş misiniz ya da pisi paket yöneticinizden yüklemiş misiniz:


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)


Burada try bloğu içinde yer alan ifade("import pygame") test edilir; hata varsa except bloğunda verilen hataya bakılır. Hatalar uyuşuyorsa except bloğu çalıştırılır; traceback ile başlayan soğuk cümleler yerine bizim programımızda yer alan kullanıcı dostu arkadaş cümleler kullanılabilir ve kullanıcının yüreği ferah tutulmuş olur.

Kök sınıfımız(miras veren sınıf) ProgressImage'ı yazmaya başlayalım:


class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init() #1.
self.screen = pygame.display.set_mode(size) #2.
self.bar = pygame.Surface((size[0]-10,size[1]-10)) #3.
self.bar.fill(initcolor) #4.
pygame.display.update(self.screen.blit(self.bar, (5,5))) #5.

def quit(self):
pygame.display.quit()



  1. Bu sınıfı iyi inceleyelim. Pygame bilenler ne yapıldığını aşağı yukarı anlayacaklardır ama bilmeyen ya da az bilenler için açıklayalım:
    pygame.display.init() satırı display modülünü başlangıçlandırır. Değer döndürmez. Bu metod kullanılmadan önce pygame.display.SDL_VIDEODRIVER ortam değişkeninin -eğer isteniyorsa- değiştirilmesi mümkündür. Böylece kullanılacak video sürücüsü seçilebilir. (Ayrıntı için bakınız)

  2. pygame.display.set_mode() metodu görüntüyü ayarlar ve 3 argüman alır. Bize sadece iki tanesi hatta biri gerekecek. İlk argüman genişlik ve yükseklik değerlerini içeren bir sabit listedir.(tuple) Burada (genislik, yukseklik) şeklinde geçecektir. İkinci argüman flags parametresidir. Bu da görüntü modunu seçmeye yarar. Kodumuzda size parametresiyle yetinilmiştir. Bu metod geriye bir Surface nesnesi döndürür.

    • Surface görüntüleri pixeller halinde saklayan bir nesnedir.
    • Yeni bir nesne oluştururken tual = pygame.Surface((100,100)) şeklinde kullanılabilir. Bu tual isminde bir yüzey nesnesi oluşturacaktır.
    • Örneğimizde self.screen = pygame.display.set_mode(size) kodu screen isminde bir Surface nesnesini display modülünün ilk kez oluşturduğu ana ekrandan almaktadır.
    • screen artık ana ekrana referans etmektedir.


  3. self.bar = pygame.Surface((size[0]-10,size[1]-10))
    satırında da az önce gördüğümüz gibi bir Surface nesnesi yaratılmaktadır. Bu nesneyi screen ana ekranının üzerine çizeceğiz; çünkü bu nesne göstergemizin görüneceği nesne olacak(siz buna katman(layer) da diyebilirsiniz). Göstergenin boyutu screen nesnesinin boyutuna göre 5 piksel içerde görünecek.

  4. self.bar.fill(initcolor) satırında elde ettiğimiz bar isimli yüzey nesnesini initcolor rengiyle dolduruyoruz. Burada color hakkında şunu söylemeliyim: Kırmızı(red), Yeşil(green), Mavi(blue) değerlerini 0-255 değerleri arasında içeren bir üçlü sabit listedir color. (0,0,255) gibi(mavi)

  5. pygame.display.update(self.screen.blit(self.bar, (5,5))) satırında önce pygame.display.update() metoduna verilen parametreye bakalım.

    • self.screen.blit(self.bar, (5,5)) komutu bar nesnesini screen nesnesinin üzerine çizer. Ama bunu ekrana yansıtmaz. Dikkat: nesneleri üstüste bindirir ancak görüntünün oluşması için update() metodu çalışmaldır.
    • Bu metod yani blit() metodu Rect döndürür. Bu bar nesnesinin kapladığı dikdörtgen alanın koordinatlarını içeren başka bir nesnedir ki tahmin edeceğiniz gibi pygame.display.update() metodu Rect alır.
    • Sonuç olarak yaptığımız ana ekran nesnesi olan screen'in üzerine bar nesnesini yanlızca kapladığı alan içinde bindirmektir. Bu bütün ekranı güncellemekten daha hızlı bir metoddur.



Bu kadarı pygame için yeterli sanırım şimdi programı huzurlarınıza sunuyorum. Sizde programı dilediğiniz gibi kopyalayıp kendi başınıza birşeyler deneyebilirsiniz.


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)

class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init()
self.screen = pygame.display.set_mode(size)
self.bar = pygame.Surface((size[0]-10,size[1]-10))
self.bar.fill(initcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

class ProgressBar(ProgressImage):
def __init__(self, whole, step, size, initcolor, barcolor):
ProgressImage.__init__(self, size, initcolor, barcolor)
self.size = size
self.initcolor = initcolor
self.barcolor = barcolor
self.whole = whole
self.step = step
if whole < step:
print "Error: ProgressBar length can't be smaller than step"
sys.exit(1)
self.slice = float(step)/float(whole)
self.percent = 0.0

def showprogress(self):
self.screen.fill(self.initcolor)
barwidth = (self.size[0]-10)*self.percent
barheight = self.size[1]-10
self.bar = pygame.Surface((barwidth,barheight))
self.bar.fill(self.barcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

def reset(self):
self.percent = 0.0
self.showprogress()

def makestep(self):
if self.percent < 1.0:
self.percent += self.slice
self.showprogress()

def quit(self):
pygame.display.quit()

def isEnd(self):
if self.percent<=1.0:
return False
else:
return True

if __name__ == "__main__":
pb = ProgressBar(1000, 10, (100,40), (255,255,255), (0,0,255))
i, j, k = 0, 0, 0
while not pb.isEnd():
temp = "running.."
for j in range(5):
for k in range(5):
print temp
pb.makestep()
pb.quit()


progressbar.png
Hepinize kolay gelsin :)

5 Ocak 2009 Pazartesi

Tkinter ile Bir Deneme: Sözcükleri Çoğul Yapma

Merhaba Arkadaşlar;
Bugün küçük bir form penceresi oluşturacağız. Penceremizde iki metin girdisi(Entry), iki etiket(Label), bir adet düğme(Button) olacak. Programımız form aracılığı ile birinci metin girdisinden alacağı türkçe kelime girdisini ikinci metin girdisinde çoğul olarak gösterecek. Ve üstelik bunların hepsini Python ile ve komut satırından çıkmadan yapacağız.

Önce program çekirdeğini oluşturacak "plurize(word)"(cogulyap(kelime)) metodunu yazalım. Bu metod word katarını(string) alır ve çoğul olan kelimeyi( : word + postfix) döndürür. Bunun için türkçedeki kurallara bir bakalım:
Türkçede son hecesi ince(e,i,ö,ü) sesli(vowel) olan kelimelere 'ler' eki(postfix) eklenir.
Son hecesi kalın(a,ı,o,u) sesli(vowel) olan kelimelere 'lar' eki(postfix) eklenir.
Türkçede heceler dört harfli ise sesli harf(vowel) baştan ikinci harftir.
Türkçede üç sessiz harf yanyana gelmez.

Şimdi bu kurallara göre bir fonksiyon oluşturalım. Daha sonra kullanıcı arayüzünü(user interface) oluşturmaya geçeceğiz.

Bunun için önerdiğim çözüm şöyle başlıyor:


vowelMatrix = {
'back': {'vowels' : (a, ı, o, u), 'postfix': 'lar'}
'front': {'vowels' : (e, i, ö, ü), 'postfix': 'ler'}
}


Bu sözlük yapısı bize arama ve karşılaştırma yaparken lazım olacak. Burada;
vowelMatrix['back'] = {'vowels' : (a, ı, o, u), 'postfix': 'lar'}
vowelMatrix['front'] = {'vowels' : (e, i, ö, ü), 'postfix': 'ler'}
vowelMatrix[0][vowels][3] = u

Fonksiyonumuzu yazalım:


def plurize(self, word):
'''Dört ya da daha fazla harften oluşan kelimelerde geçerlik sınaması yapar.
wordü çoğul yapar ve döndürür'''
isValid = None
letters = list(word) #harfler
backVowels = self.vowelMatrix['back']['vowels']
frontVowels = self.vowelMatrix['front']['vowels']
triad = letters[:3] #üçlü harf listesi
if len(letters) > 4:
#Dört sesten uzun kelimeler için
for letter in letters: # geçerli bir sözcük mü
if letter == ' ': # içinde boşluk içeriyorsa
return None # Hata.
for l in triad: # Üç sessiz harf ardarda geliyor mu
if (l in backVowels) or (l in frontVowels):
#üçlüdekilerden biri bile sesli ise geçerli.
isValid = True
break #tamam kelime geçerli
else:
#yoksa geçersizdir
isValid = False
if isValid:
#kelimede sesli harf varsa
tetrad = []*4 #geçici dörtlü
tetrad[:3] = triad #ilk üç sesi üçlüden
tetrad.append(letter) #dördüncü sesi sıradaki sesten aldık
triad = tetrad[1:] #son üç sesi üçlüye yükledik
else:
#üç sessiz ardarda gelmiş.
return None #Hata.
#Kelime geçerli.
#Şimdi çoğul yapma algoritması:
if (letters[-1] in backVowels) or (letters[-2] in backVowels):
#Sondan birinci harf ya da ikincisi kalın ise..
#kelimeye uygun eki(postfix) yani 'lar' ekini ekle ve döndür
return word + self.vowelMatrix['back']['postfix']
elif (letters[-1] in frontVowels) or (letters[-2] in frontVowels):
#Sondan birinci harf ya da ikincisi ince ise..
#kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür
return word + self.vowelMatrix['front']['postfix']
elif len(letters) == 4:
# 4 harfli ise 2. harfi sesli olabilir; 2. 4. sesi sesli olabilir;
# 2. 3. sesi 'a' olabilir:
if ((letters[0] not in backVowels) or (letters[0] not in frontVowels)) \
and ((letters[2] not in backVowels) or (letters[2] not in frontVowels)) \
and ((letters[3] not in backVowels) or (letters[3] not in frontVowels)) \
and ((letters[1] in backVowels) or (letters[1] in frontVowels)):
#1.3.4. sesler sessiz; 2. ses sesli ise(kask, türk gibi)
return letters[1] in backVowels \
and word + self.vowelMatrix['back']['postfix'] \
or word + self.vowelMatrix['front']['postfix']
elif (letters[1] == 'a') and (letters[2] == 'a'):
#2. ve 3. ses 'a' ise(saat, maaş gibi)
#kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür
return word + self.vowelMatrix['front']['postfix']
elif ((letters[1] in backVowels) or (letters[1] in frontVowels)) \
and ((letters[3] in backVowels) or (letters[3] in frontVowels)):
#2. 4. sesler sesli ise(pepe, lapa gibi)
return letters[1] in backVowels \
and word + self.vowelMatrix['back']['postfix'] \
or word + self.vowelMatrix['front']['postfix']
elif letters[3] in frontVowels:
#4. sesli ince ise
#kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür
return word + self.vowelMatrix['front']['postfix']
else:
#kelime geçersizse
return None #Hata.
elif len(letters) == 3:
#3 harfli ise salt 2. harfi sesli olabilir;
#ya da salt 1. ve 3. sesler sesli olabilir:
if (letters[1] in backVowels) or (letters[1] in frontVowels) <>\
~( (letters[0] in backVowels or letters[0] in frontVowels) \
and (letters[2] in backVowels or letters[2] in frontVowels) ):
#1. ve 3. ses sessiz, 2. ses sesli ise ya da tersi
if (letters[1] in backVowels) or (letters[1] in frontVowels):
#2. ses sesli ise
#kelimeye uygun eki(postfix) ve döndür
return letters[1] in backVowels \
and word + self.vowelMatrix['back']['postfix'] \
or word + self.vowelMatrix['front']['postfix']
else:
#2. ses sessiz ise
#kelimeye uygun eki(postfix) ve döndür
return letters[2] in backVowels \
and word + self.vowelMatrix['back']['postfix'] \
or word + self.vowelMatrix['front']['postfix']
else:
#kelime geçersizse
return None #Hata.
elif len(letters) == 2:
#2 harfli ise ya birinci harf sesli ikincisi sessizdir ya da tersi
if not ( ((letters[0] in backVowels) or (letters[0] in frontVowels)) <> \
((letters[1] in backVowels) or (letters[1] in frontVowels)) ):
#iki ses de sesli ya da iki ses de sessiz ise hata. (aa, kk)
return None
elif ( (letters[0] in backVowels or letters[0] in frontVowels) <> \
~(letters[1] in backVowels or letters[1] in frontVowels) ):
#ya birinci harf sesli ikincisi sessizdir ya da tersi(ka, ak)
return (letters[0] in backVowels or letters[1] in backVowels) \
and word + self.vowelMatrix['back']['postfix'] \
or word + self.vowelMatrix['front']['postfix']
else:
#Başka olasılık kalmadı; ama denemeye değer:
return None
elif len(letters) == 1 or word == None:
return None


Burada yapılan işlem yukarıda sıraladığım kuralları program mantığına uyarlamak. Sırasıyla 4 sesten büyük, 4 sesli, 3 sesli, 2 sesli ve 1 sesli durumları sınandı.

Dialog Sınıfını yazarken bu fonksiyonu(işlevi) def plurize(self, word)
şeklinde ekleyeceğiz. Tkinter ile kullanıcı arayüzü(user interface) içeren uygulamalar yazmak için öncelikle kodumuza uygun modülleri "import" etmeliyiz:

# -*- coding: utf-8 -*-
#!usr/bin/python
from Tkinter import *


Bu kod ile Tkinter modülünden bütün sınıfları içerdik(import, include). Artık örneğin Label sınıfını kullanırken "Tkinter.Label" şeklinde açımlamak zorunda kalmayacağız. Doğrudan "Label" şeklinde açımlama(decleration) yapabileceğiz.
Şimdi sınıf mantığı ile Tkinter nasıl birleştirilir onu görelim. Bir etiket yapmak o kadar kolay değil; belki de çok kolay ;)

class PlurizeDialog:
def __init__(self, master):
pass


Burada PlurizeDialog isimli bir sınıf tanımladık. Bu bizim UI(user interface : kullanıcı arayüzü) sınıfımız. Bu sınıfın yapıcısı(constructor) __init__() işlevi. Bu işleve dikkat:

def __init__(self, master):

Bu kod içinde yer alan master parametresi root = Tk() ile yaratacağımız ana pencerenin referansını alacak. Yani
root = Tk()
pl = PlurizeDialog(root)

diyebilmek için master parametresini kullanıyoruz.
Geri kalan işlemler basit:

Label(master, text='Enter Turkish:').pack()
self.e1 = Entry(master)
self.e1.pack(padx=18)
Label(master, text='Plural:').pack(pady=3)
self.e2 = Entry(master)
self.e2.pack(pady=3, padx=18)
b = Button(master, text='Plurize', command=self.show_plurize)
b.pack(pady=9)

kodu ile __init__() bitiyor. Burada yaptığımız Label ile iki tane etiket oluşturmak. Entry ile iki metin girdisi oluşturmak, Button ile bir düğme eklemek. Burada command=show_plurize atamasına dikkat. Düğmeye tıklandığında çalışacak olan show_plurize() şimdi geliyor:

def show_plurize(self):
word = self.e1.get()
newWord = self.plurize(word)
if newWord != None:
self.e2.insert(0, newWord)
else:
self.e2.insert(0, "Invalid Word!")


Burada b düğmesine tıklandığında çalışacak işlev görülüyor. plurize() işlevini kullanan bu işlev sayesinde kod kısmı ile ui kısmını ayırmış olduk.

İşte Dialog Sınıfı ve programın son hali:


# -*- coding: utf-8 -*-

from Tkinter import *

class PlurizeDialog:
def __init__(self, master):
Label(master, text='Enter Turkish:').pack()
self.e1 = Entry(master)
self.e1.pack(padx=18)
Label(master, text='Plural:').pack(pady=3)
self.e2 = Entry(master)
self.e2.pack(pady=3, padx=18)
b = Button(master, text='Plurize', command=self.show_plurize)
b.pack(pady=9)
vowelMatrix = { \
'back': {'vowels' : ('a', 'ı', 'o', 'u'), 'postfix': 'lar'}, \
'front': {'vowels' : ('e', 'i', 'ö', 'ü'), 'postfix': 'ler'} \
}
def show_plurize(self):
word = self.e1.get()
newWord = self.plurize(word)
if newWord != None:
self.e2.insert(0, newWord)
else:
self.e2.insert(0, "Invalid Word!")
def plurize(self, word):
pass #yukarıda verildi.

if __name__ == '__main__':
root = Tk()
pd = PlurizeDialog(root)
root.mainloop()


İyi Çalışmalar.
Özgür Sönmez.

10 Aralık 2008 Çarşamba

PyGame hakkında

Pygame, Python kullanıcıları rahatça oyun geliştirebilsin diye Pete Shinners tarafından geliştirilmeye başlanmış bir Python pakedi. İçerisinde şu modüller ile birlikte geliyor :
  • Cdrom (manage cdrom devices and audio playback)
  • Cursors (load cursor images, includes standard cursors)
  • Display (control the display window or screen)
  • Draw (draw simple shapes onto a Surface)
  • Event (manage events and the event queue)
  • Font (create and render Truetype fonts)
  • Image (save and load images)
  • Joystick (manage joystick devices)
  • Key (manage the keyboard)
  • Mouse (manage the mouse)
  • Mask
  • Mixer
  • Movie (playback of movies)
  • Music (playback of music)
  • Overlay
  • Pixelarray
  • Rect
  • Sndarray
  • Sprite
  • Surface
  • Surfarray (manipulate images with Numeric)
  • Time (control timing)
  • Transform (scale, rotate, and flip images)
Görüldüğü üzere zenginlik konusunda karun kadar zengin PyGame. Avantajlarının biri de geliştirdiğiniz uygulamanın diğer işletim sistemlerine kolayca port edilebilmesi. Hatta işleme gerek kalmaksızın Mac sistemlerde direkt olarak çalışıyor.

Bu pakedi kullanarak geliştirdiğiniz ürünleri istediğiniz her hangi bir lisans ile yayınlayabiliyorsunuz (evet para kazanmak da mümkün). Gücünü SDL (Simple DirectMedia Layer) denen bir kütüphaneden alıyor. Bahsi geçen SDL, C ve Assembly dili kullanılarak yazılmış bolca optimizasyondan geçmiş, hız konusunda tartışmasız bir biçimde tatmin edici. Anlayacağınız PyGame'in duruşu pek şirin olsa da arkasında bir canavar yatıyor.

Aslına bakarsanız bir video kurgu programı yapmak için bile uygun gördüm kendisini, "oyun yapmak için kütüphane" tanımı biraz zayıf kalıyor kendisini anlatmaya.

Evet SDL kütüphanesi çok güçlü ama "Python dili oyun programlama yapmak için uygun mu?" sorusunu cevaplamak gerekiyor.

Python çok üst seviyeli bir dil, bir C kodundan yaklaşık 20 kat yavaş çalışıyor. Zaten bu programlama dilini tercih ederken pek performansına bakarak karar vermedik hiçbirimiz. Python dilinin asıl vurucu noktası bildiğiniz gibi kolay öğrenilir olması, ve size çok çabuk çözümler sunabilmesi. Python ve PyGame ile oyun yapmaya niyetlendiyseniz, bir "enemy-territory yapayım" şeklinde hayallere dalmanız sizi hayal kırıklığına uğratır. Yapabileceğiniz genelde hafif diye tabir edebileceğimiz oyunlar. Zaten genelde PyGame ile yapılmış oyunları incelediğinizde flash oyunu türevi ya da eski ATARI-C64 oyunlarının yeniden yapılmış halleri ile karşılaşıyoruz.

Bunların yanında PyGame hoş bir topluluğa sahip.İnsanları oyun geliştirilmesine teşvik etmek amacıyla "bir hafta içerisinde en güzel oyunu kim geliştirecek?" konseptine sahip bir yarışma düzenliyorlar adı da PyWeek. Siteye uğrayıp en azından o hafta yarışmaya katılmış oyunları oylamak bile yeterince eğlenceli bir aksiyon. Gerçekten güzel işler var ve tabi ki hepsinin kodları açık.

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/

2 Ekim 2008 Perşembe

Cgi-python'a Giriş

Bu yazımızda cgi modülünü ve cgi-python ile web sayfaları yazmayı anlatacağız.
Öncelikle python destekleyen bir yer bulmalısınız veya kendi bilgisayarınızda deneyebilirsiniz.


# -*- coding: utf-8 -*-

print """\
Content-Type: text/html\n

<html>
<body> bu bir deneme sayfasıdır... </body>
</html>
"""


cgi-python da html kodları print ile yazılır.
Content-Type: text/html\n satırı ile içeriğin türünü belirttik buradaki "\n" karakteri koyduk çünkü bu satırdan sonra 2 tane "\n" olmalı.

şimdi örneğimizi geliştirelim...


# -*- coding: utf-8 -*-

import cgi

form = cgi.FieldStorage()
isim = form.getfirst("isim", "bos")

print """\
Content-Type: text/html\n

<html>
<body>
<b>Gelen isim: </b> %s
</body>
</html>
""" % str(isim)


burada cgi modülündeki FieldStorage sınıfının getfirst metodu ile "isim" adındaki argumanı aldık bu arguman index.py?isim=deneme şeklinde gelir buradaki "deneme" argumandır.
getfirst e verilen 2. arguman ise hiçbir değer gelmezse isim değişkenine atanır yani değer verilmezse değişkenin değeri "bos" olur.

örneğimizi daha da geliştirecek olursak...


# -*- coding: utf-8 -*-
import cgi

form = cgi.FieldStorage()
isim = form.getfirst("isim", "bos")

print """\
Content-Type: text/html\n
<html>
<body>
"""

if isim != "bos":
print """\n
<b> Gelen isim: </b> %s
""" % isim
else:
print """\
<form action="deneme.py">
isminiz: <input type=text name="isim">
</form>
"""

Hata yakalma:

# -*- coding: utf-8 -*-

import cgi
import cgitb

cgitb.enable()

try:
open("olmayan_doysa", "r")
except:
cgitb.handler()

Hata yakalamak istediğmizde cgitb modülünü cgitb.enable() ile aktif ediyoruz daha sonra ise hata yakalandığında cgitb.handler() i çalıştırıyoruz.

1 Ekim 2008 Çarşamba

Django Şablonları İçin Özel Etiketler

Django Şablonları İçin Özel Etiketler

İçeriğinde forum, günlük, anket vb. uygulamaların olduğu bir projeniz olduğunu düşünün. Ve siz forum uygulamasındaki son eklenen konuları, günlük uygulaması içerisinde kullanmak istiyorsunuz. Bu durumda ne yaparsınız? Günlük uygulamasının views.py dosyası içerisinden forum uygulaması tablosuna bağlanarak son eklenen konuları almazsınız umarım. Çünkü Django şablon dosyaları içerisinde, kendi yazdığımız etiketleri kullanabiliyoruz. Bu yazıda şablon dosyaları için uygulamanıza özel etiketleri nasıl oluşturacağınızı göstermeye çalışacağım.


İlk olarak projemizi ve uygulamamızı oluşturalım. Oluşturacağımız templates klasörü şablon dosyalarımızı, templatetags klasörü ise özel etiketlerimizle ilgili dosyaları içerisinde barındıracak.



$ djangoadmin.py startproject mysite
$ cd mysite
$ python manage.py startapp ozeletiketler
$ mkdir ozeletiketler/templates ozeletiketler/templatetags


Ardından settings.py dosyamızdaki TEMPLATE_DIRS ve INSTALLED_APPS ayarlarını düzenleyelim. Burada şablon dosyaları için proje dizinimizi hedef gösterdik. Bu şekilde Django, uygulamalarımızın altında bulunan templates ve templatetags klasörlerini tanıyabilecektir.




TEMPLATE_DIRS = (
[...]
'/home/omer/django-projects/mysite'
[...]
)


INSTALLED_APPS = (
[...]
'mysite.ozeletiketler'
)


Şimdide urls.py dosyamızı düzenleyelim.

urlpatterns = patterns('',
[...]
(r'^ozeletiketler/','mysite.ozeletiketler.views.index'),
[...]
)


Bu yaptığımız değişiklikleri test etmek için ozeletiketler uygulaması içindeki views.py dosyasını aşağıdaki gibi düzenliyor ve ardından templates klasöründe index.html dosyasını oluşturup tarayıcıda boş sayfa(ya da içine bir şeyler yazdıysanız onların) çıkıp çıkmadığını kontrol ediyoruz.



#-*- coding: utf-8 -*-
from django.shortcuts import render_to_response

def index(request):
return render_to_response('ozeletiketler/templates/index.html',{})
return render_to_response('index.html',{})


Boş sayfayı gördük, işler yolunda. Bir sonraki aşamaya geçelim. templatetags klasörü altında __init__.py ve ozeletiketler.py adlı dosyaları oluşturalım. __init__.py dosyası içeriği boş kalırken, ozeletiketler.py dosyası içeriği aşağıdaki şekilde olmalı.



#-*- coding: utf-8 -*-
from django.template import Library,Node

register = Library()

def beniyaz(veri):
return veri
register.simple_tag(beniyaz)


class IslemNode(Node):
def __init__(self,nodelist,bits):
self.nodelist = nodelist
self.bits = bits

def render(self,context):
islem = self.nodelist.render(context)
sonuc = eval(islem)
if self.bits.__len__()>1:
if self.bits[1] == 'sadece_sonuc':
return sonuc
return u"Yapılan İşlem %s : %s" %(islem,sonuc)

def islem(parser,token):
nodelist = parser.parse(('islembitti',))
parser.delete_first_token()
bits = token.contents.split(' ')
return IslemNode(nodelist,bits)
register.tag(islem)


Şimdi bu oluşturduğumuz özel etiketlerimizi şablon dosyamız içerisinde (önceden oluşturmuştuk: index.html) kullanalım.

{% load ozeletiketler %}

{% beniyaz "merhaba dünya" %}


{% islem %} 20 + 5 {% islembitti %}


{% islem sadece_sonuc %} 11 - 4 {% islembitti %}


Bu işlemin ardından http://127.0.0.1:8000/ozeletiketler/ adresini ziyaret ettiğinizde aşağıdaki çıktı ile karşılaşacaksınız:



Son olarak yapılan işlemlerle ilgili bazı konulara açıklık getirelim.

Ozeletiketler.py Dosyası

Library ve Node sınıflarını dahil ettik. Etiketleri kaydetmek için register değişkenine Library sınıfını atadık. Library sınıfı etiketleri şablon dosyaları içerisinde kullanabilmek için kaydetmemizi sağlar. Node sınıfı ise etiketlerin kullanılması ile gelen veriyi yorumlayıp geri döndürmeyi sağlar.

#-*- coding: utf-8 -*-
from django.template import Library,Node

register = Library()


Gelen veriyi geri döndüren basit bir etiket oluşturduk. Ardından register değişkenini kullanarak etiketi kaydettik. register değişkenine Library sınıfını atamıştık. simple_tag Library sınıfının bir fonksiyonudur.

def beniyaz(veri):
return veri
register.simple_tag(beniyaz)


Daha gelişmiş bir etiket oluşturduk ve bunu register.tag ile (tag Library sınıfının bir fonksiyonudur) kaydettik. islem fonksiyonu içerisinde ise nodelist değişkenine etiketin ilk ve son kısımları arasındaki içeriği aldık. Etiketimizin bitiş kısmını burada islembitti değeri ile belirledik. Yani {% islem %} ... {% islembitti %} arasındaki içerik bu etiketin alanı olacak. bits değişkenine de etiket açılışında tanımlanan verileri aktardık ( örn: {% etiket_adi veri1 veri2 ...% } deki veri1, veri2 vb. değerleri). Ardından bu değişkenleri(nodelist,bits), işlenip geri dönmesi için IslemNode sınıfına aktardık.

def islem(parser,token):
nodelist = parser.parse(('islembitti',))
parser.delete_first_token()
bits = token.contents.split(' ')
return IslemNode(nodelist,bits)
register.tag(islem)


Eğer oluşturmuş olduğumuz islem etiketi şablon dosyasında kullanılırsa, bu etiketin yorumlanması sırasında IslemNode sınıfı içerisindeki render fonksiyonu devreye girecektir. Bu fonksiyon devreye girdiğinde, önce {% islem %} {% islembitti %} arasındaki verileri yorumlayacak, ardından bunu icerik değişkenine aktaracak. islem etiketi ile gelen verilere göre(bits) kontrol yapılıp geriye sonucu döndürecektir.

Tabi bu bizim aşağıdaki sınıf için geçerli. Siz render fonksiyonu içerisinde kendi etiketinize göre işlemleri yaptırmalısınız. Bilmeniz gereken render fonksiyonu içerisinde bulunan self.nodelist.render(context) ile etiketinizin içeriğinin görüntülenebilir halini alabilmenizdir.

class IslemNode(Node):
def __init__(self,nodelist,bits):
self.nodelist = nodelist
self.bits = bits

def render(self,context):
icerik = self.nodelist.render(context)
sonuc = eval(icerik)
if self.bits.__len__()>1:
if self.bits[1] == 'sadece_sonuc':
return sonuc
return u"Yapılan İşlem %s : %s" %(icerik,sonuc)


Index.html Dosyası

Yazdığımız ozeletiketler.py dosyamızı şablon dosyası içerisine dahil ettik. Böylelikle bu dosya içerisindeki özel etiketleri kullanabildik. Buradaki ozeletiketler dosyamızın ismidir. templatetags içerisinde dosyaları herhangi bir isimde oluşturabilirsiniz. load ile kullanım sırasında ise oluşturduğunuz dosya ismini belirtmelisiniz.

{% load ozeletiketler %}


beniyaz isimli etikete bir değer vererek, değeri ekrana yazdırdık.

{% beniyaz "merhaba dünya" %}


İşlemin, açıklamalı olarak ekrana yazdırılmasını sağladık.

{% islem %} 20 + 5 {% islembitti %}


İşlemin sadece sonucunun ekrana yazdırılmasını sağladık.

{% islem sadece_sonuc %} 11 - 4 {% islembitti %}


Açıklamalar belki kafa karıştırıcı olabilir. Bunu en aza indirmeye çalıştım. Aklınıza bir kaç soru gelebilir. Belki bunları tahmin edebilirim düşüncesiyle kendi kendime bir kaç soru sorup cevaplarını vermeye çalışacağım.

1 - Etiket isimlerini nasıl belirliyoruz?
Etiket ismi, özel etiket dosyanızda belirlediğiniz fonksiyon ismidir. Eğer farklı bir isim kullanmak isterseniz register.tag fonksiyonunu aşağıdaki gibi kullanmalısınız. register.simple_tag için böyle bir özellik bulunmuyor.


register.tag("yeni_etiket_adi",fonksiyon_adi)


2 - Etiket açılışında tanımlanan verileri ayırma işlemini ne şekilde yapabilirim?

Bu işlemi token.contents.split(' ') bölümünden gerçekleştirebilirsiniz. Örneğin boşluk yerine tırnak ile verileri ayırmak isteyebilirsiniz. Bunun için aşağıdaki gibi bir kullanım işinizi görecektir.


def islem(parser,token):
[...]
bits = token.contents.split('\"')
[...]



[...]
{% islem "sadece_sonuc" ... %}
[...]


3 - Daha fazlası için?

django/template/defaulttags.py dosyasını inceleyebilirsiniz.

29 Eylül 2008 Pazartesi

Django ile Anket 3

Bundan önceki uygulamarımızda anket oluşturmak, düzenlemek ve yeni seçenekler eklemek gibi bir takım ayarları yapmayı öğrenmiştik. Ama bunları sadece admin paneli üzerinden yapıyorduk. Peki bu anketleri nasıl sayfamızda gösterebiliriz ?

Anketleri sayfamızda gösterebilmemiz için anket uygulaması içerisinde yer alan view.py dosyasında bir takım düzenlemeler yapmamız gerekiyor. View.py dosyasının içeriğini şu hale getirelim.

from django.template import Context, loader
from OrnekProje.anket.models import Anket
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404

def index(request):
son_anketler = Anket.objects.all().order_by('-yayin_tarihi')[:5]
return render_to_response('anket/index.html',{'son_anketler':son_anketler })

def detail(request, anket_id):
p = get_object_or_404(Anket, pk=anket_id)
return render_to_response('anket/detail.html', {'anket': p})

def all(request):
anketler = Anket.objects.all().order_by('-yayin_tarihi')
return render_to_response('anket/all.html',{'anketler':anketler})

Ardından urls.py dosyanını şu şekilde düzenleyin. Bu arada yukarıda ki kodlar için acele etmeyin hepsini açıklayacağım ;)

urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),
(r'^anket/$', 'OrnekProje.anket.views.index'), #[1]
(r'^anket/(?P\d+)/$','OrnekProje.anket.views.detail'),
(r'^anket/all/$','OrnekProje.anket.views.all'),


Öncelikle urls.py dosyasından başlayalım. #[1] ile biten satıra bakalım. Bu satırda djangoya /anket/ adresine gelen bir istek olursa OrnekProje/anket/views dosyasından index fonksiyonun çalıştırılması isteniyor. ( url tanımı yapılırken kullanılan düzenli ifadelerden gökmen ve mirat daha önceki yazılarında bahsettikleri için uzun uzun değinmiyorum.) Şimdi gelelim index fonksiyonuna. İlk satırda son_anketler isimli değişkene veri tabanındaki son 5 anketi tarih sırasına göre atıyoruz. 2. satırda ise render_to_response nesnesini kullanarak
anket dizini içerisindeki index.html dosyanı son_anketler ile verilen değerleri kullanarak bir değer döndürmesini istiyoruz. (Sanki biraz karışık bir cümle oldu :/)

Ama sanki bir şey unuttuk ? anket/index.html diye bir dizin ve dosya yaratmadık. Şimdi OrnekProje dizini içerisinde Templates diye bir dizin oluşturalım. Burada tüm templatelerimizi saklayalım. İyi bir gruplandırma olması açısından her uygulama için ayrı bir dizin kullanalım. Yani onunda içerisinde bir anket dizini oluşturalım.

Bu dizinleri oluşturduktan sonra bunlardan djangoyu haberdar etmeye geldi sıra. Bunun için settings.py dosyasındaki TEMPLATE_DIRS satırını şu şekilde değiştirmemiz gerekiyor.

TEMPLATE_DIRS = ("/home/Deniz/OrnekProje/templates" # dizini kendi dizininizle değiştirmeri unutmayın :)
)


Şimdi tekrar templates/anket klasörüne gidip index.html dosyasını oluşturup içeriğini şu şekilde dolduralım.

{% if son_anketler %}
<ul>
{% for anket in son_anketler %}
<li>{{ anket.soru }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}



İlk satırda ki if sorgusu ile eğer son_anketler değeri var ise aşağıdaki işlemleri yapmasını söylüyoruz.

for döngüsü ise anket olduğu sürece anket sorularını ekrana bastırmamıza yarıyor.

Eğer if sorgusu False değeri döndürürse (yani hiç anket yoksa) else bloğu işletiliyor.

Burada sadece anket sorularını ekrana yazdırdık.

Şimdi urls.py dosyamızın 2. satırını ve detail fonksiyonunu açıklayalım. 2. satırda "/anket/2" "/anket/3" gibi sayfalara gelen isteklerde anket numarasına göre o anketi kullanmamızı için anket_id değerini parametre olarak detail fonksiyonuna gönderiyor.


def detail(request, anket_id):
p = get_object_or_404(Anket, pk=anket_id)
return render_to_response('anket/detail.html', {'anket': p})


Burda da farklı olarak get_object_or_404 nesnesini kullandık. Bu nesne eğer anket_id değeri ile gelen bir değer yoksa ekrana sayfa bulunamadı yazdırmamızı sağlıyor.

Bu da detail.html dosyamızın içeriği

<h1>{{ anket.soru }}</h1>
<ul>
{% for secim in anket.secim_set.all %}
<li>{{ secim.secenek }}</li>
{% endfor %}
</ul>


Burada 3 numaralı anketimizi görüntüledik.

Son fonksiyomuz olan all ve urls.py dosyasındaki ona ait olan satırı uzun uzun anlatmayacağım. Önceki bilgilerimiz ile neyin ne olduğunu anlayabiliriz :) Burada da tüm anketlerimizi ve şıklarını aynı anda sayfaya yazdırıyoruz.

all.html dosyasının içeriği;


{% for anket in anketler %}
<h3> {{anket.soru}} </h3>
{% for secim in anket.secim_set.all %}
<li> {{secim.secenek}} </li>
{% endfor %}
{% endfor %}




Yine template dosyaları aracılığıyla bu yazdıklarımızı özelleştirmek sizin elinizde ;)

23 Eylül 2008 Salı

Django ile Anket

Bu uygulamamızın temel amacı django ile admin panelini anlatmak olacak. O yüzden onun dışında kalan bölümleri hızlıca geçeceğim.O bölümler daha önce gökmen ve mirat tarafından ayrıntılı olarak anlatılmıştı. Eğer başlangıçtaki bazı örnekleri anlayamazsanız daha önce yazılmış django notlarından faydalanabilirsiniz.

Şimdi yeni bir proje başlatmak için gerekli olan komutumuzu veriyoruz.

Deniz@ParMak ~ $ django-admin.py startproject OrnekProje

OrnekProje adıyla yeni bir projeye başladık şimdi o dizine geçip uygulamamıza devam edelim.

Deniz@ParMak ~ $ cd OrnekProje/


Şimdi de projemiz içerisinde yeni bir uygulama başlatalım.
Not: Uygulamalar genellikle belirlir bir görevi yerine getirmek üzere kullanılırken. Projeyi ise içinde bir çok uygulamayı içerisinde düzenli şekilde barındıran uygulamalar bütünü olarak tanımlayabiliriz. Yine uygulamalarımızı bir kere oluşturup farklı projeler içerisinde de kullabiliriz.

Deniz@ParMak OrnekProje $ python manage.py startapp anket

Projemiz içerisinde anket isimli bir dizin oluştuğunu göreceksiniz içinde ise "__init__.py __init__.pyo models.py models.pyo views.py views.pyo " dosyaları mevcuttur.

models.py dosyası bizim modellerimizi tanımlayacağımız dosya olacak. Anket uygulaması için 2 model oluşturacağız: Anket ve Secim. Anket içerisinde soru ve yayın tarihi yer alırken Secim içerisinde secenekler ve oylar alanları yer alacak. Bunun için aşağıda ki kodları models.py dosyamıza kaydediyoruz.

from django.db import models

class Anket(models.Model):
soru = models.CharField(max_length=200)
yayin_tarihi = models.DateTimeField('yayin tarihi')

class Secim(models.Model):
anket = models.ForeignKey(Anket)
secenek = models.CharField(max_length=200)
oylar = models.IntegerField()


Şimdide bir üst dizinde yer alan settings.py dosyasında INSTALLED_APPS kısmını şu şekilde düzenliyoruz.


INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'OrnekProje.anket',
)


Şimdi veri tabanı ayarlarını düzenliyoruz. (Ayrıntılı bilgi için miratın yazını inceleyiniz.


DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'veritabanı_ismi' # Or path to database file if using sqlite3.
DATABASE_USER = 'Deniz' # Not used with sqlite3.
DATABASE_PASSWORD = 'şifrem' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.

Eğer Pardus kullanıyorsanız Tasma-Servis Yöneticisinden mysql_server'i çalıştırmayı unutmayınız.

Ardından bakalım az önce models.py içerisine pythoncasını yazdığımız modellerin mysql karşılıkları nelermiş ?

Deniz@ParMak OrnekProje $ python manage.py sql anket
BEGIN;
CREATE TABLE `anket_anket` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`soru` varchar(200) NOT NULL,
`yayin_tarihi` datetime NOT NULL
)
;
CREATE TABLE `anket_secim` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`anket_id` integer NOT NULL,
`secenek` varchar(200) NOT NULL,
`oylar` integer NOT NULL
)
;
ALTER TABLE `anket_secim` ADD CONSTRAINT anket_id_refs_id_4e3e5fcb FOREIGN KEY (`anket_id`) REFERENCES `anket_anket` (`id`);
COMMIT;


Eğer benzer bir çıktı aldıysanız herşey yolunda devam edebiliriz.
Eğer bir hata almadıysanız djangoya az önceki sql komutlarını çalıştırmasını söylemek için aşağıda ki komutu giriyoruz.

python manage.py syncdb

Çıktısında şöyle birşey göreceksiniz.

Creating table anket_anket
Creating table anket_secim
Installing index for anket.Secim model

Şu ana kadar veri tabanı ayarlarımız yaptık şimdi Admin paneliyle ilgili ayarlarımıza geçiyorum.

Tekrar setting.py dosyasını açıp INSTALLED_APPS bölümüne az önceki örnekteki gibi 'django.contrib.admin' satırını ekliyoruz.

Ardından tekrar python "manage.py syncdb" komutunu verip veri tabanını güncellemesini istiyoruz. Bu esnada sizden admin paneline girişte kullanmanız için bir kullanıcı adı ve şifresi isteyecek gerekli ayarları yapıp devam ediniz.

Son olarakta urls.py dosyasının başında admin paneli için gerekli olan modülleri yüklemek için # işaretini kaldırıyoruz. Ve yine o dosyanın sonundaki admin alanını djangoya göstermek için oradan da # işaretini kaldırıyoruz.
Yani dosyanın en son hali şu şekilde olacak.

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
# Example:
# (r'^OrnekProje/', include('OrnekProje.foo.urls')),

# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),

# Uncomment the next line to enable the admin:
(r'^admin/(.*)', admin.site.root), #burasını
)

Şimdi django sunucusunu çalıştıralım.

python manage.py runserver

Şimdi tarayıcınızdan http://127.0.0.1:8000/admin/ adresini açıp neler olduğuna bakabilirsiniz :)

Biraz kurcalayınca Gruplar,Kullanıcılar ve Siteler adında 3 bölüm göreceksiniz. Bunlar django ile öntanımlı olarak gelen admin paneli araçlarıdır. Fakat sanki bizim anket piyasada görünmüyor ? Bunun için yapmamız gereken tek birşey daha kaldı. Anket dizini içerisine admin.py adında bir dosya oluşturup içerisine şu satırları eklemek.

from OrnekProje.anket.models import Anket
from django.contrib import admin

admin.site.register(Anket)


Şimdi sunucumuzu yeniden başlatalım.(Ctrl+c) ile sonlandırıp. python manage.py runserver ile yeniden başlatabilirsiniz.

Eğer bir aksilik çıkmadıysa artık admin panelinde anket uygulamımızı görmüşsünüzdür. Aslında buradan sonra anlatılacak pek birşey kalmıyor ama ben kısaca bir kaç ufak şeyden bahsedeyim.

*Anketlere girdiğimizde görmüş olduğumuz form anket modelinde yazmış olduğumuz koda göre django tarafından otomatik olarak oluşturuluyor.

*Anket modelinde oluşturduğumuz alanları hatırlayacak olursanız (DateTimeField, CharField gibi) django bunlara bakarak admin panelinde ona göre bir html üretiyor.

*Örneğin DateTimeField ile gün ayarı yapabileceğimiz bir JavaScript kısayolunu bizim için panele ekliyor.

Şimdilik bu kadarla kesiyorum. Admin panelinide kendi isteğimize göre özelleştirebiliyoruz. İlerleyen günlerde bu ufak tefek özelleştirmelerden de bahsedebilirim.

19 Eylül 2008 Cuma

Ev Yapımı Şifreleme

Merhaba.
Bugün size Python ile ev yapımı şifreleme nasıl yapılır ondan bahsedeceğim. Ev yapımı şifrelemeden neyi kastettiğimi yazının devamında daha rahat anlayacaksınız.
(Not: Yazar girişte başlığı kullanarak merak uyandırmaya çalışmış ve okuyucuyu yazının devamını okuması için teşvik etmeye çalışmıştır).

Programı görmeden önce size bu programı nerede kullanabileceğinizden bahsedeceğim, programın bu bilgiyle incelendiğinde daha kolay anlaşılacağını düşünüyorum.

Senaryomuz şöyle;

Bir uygulama geliştirdiniz. Uygulamanız kullanıcı adı ve şifre girişi gerektirmekte ve sizde bu kullanıcı adını ve şifreyi kullanıcının bilgisayarında tutmak durumundasınız. Sadece bir kullanıcının kullanıcı adı ve şifresini tutmak içinde veritabanı kullanmak istemiyorsunuz. Bu durumda bu bilgileri bir dosyada tutmanız gerek. Buraya kadar her şey normal. Sorun bu bilgileri o dosyada nasıl tutacağınız. Bir dosya oluşturup içerisine pattadanak (böylemi yazılıyor bu?) yazacak değilsiniz. Bu kadarla da kalmıyorsunuz programınız kullanıcınızın izni dışında 3. şahıslar tarafından kopyalandığında da o 3. şahıs programını çaldığı kullanıcınızın bilgileri ile giriş yapamasın istiyorsunuz, yok artık!!! İşte bu yazıda böyle bir ihtiyaç durumunda kullanabileceğiniz bir şifreleme yönteminden, kendi verdiğim isimle "Ev Yapımı Şifreleme" den bahsedeceğim.

Çok konuştuk, kodu görelim. Önce kodun tamamını verip daha sonra parça parça açıklamasını vereceğim.

import operator
import sys,os

class Encrypt():
def xor(self, password,encrypt=True):
key=self.mix_mac()
if not encrypt:
key+='\x00'
p_sira = -1
encrypted = ""
for str_sira in range(len(key)):
p_sira += 1
if (p_sira >= len(password)): p_sira = 0
p = str(password[p_sira])
s = str(key[str_sira])
e = chr ( operator.xor(ord(s), ord(p)))
encrypted += e
if encrypt:
encrypted += str(len(password))
return encrypted

def decrypt(self,enc):
enc_len=int(enc[len(enc)-1])
return enc[:enc_len]

def mix_mac(self):
mac=self.getMacAddress()
KEY='pythontr'
mixed_mac=''
str_mac=str(mac)

for i in range(len(KEY)):
mixed_mac+=str_mac[i]+KEY[i]
mixed_mac+=str_mac[len(KEY):]
return mixed_mac

def getMacAddress(self):
if sys.platform == 'win32':
for line in os.popen("ipconfig /all"):
if line.lstrip().startswith('Physical Address'):
mac = line.split(':')[1].strip().replace('-',':')
break
else:
for line in os.popen("/sbin/ifconfig"):
if line.find('Ether') > -1:
mac = line.split()[4]
break
return mac


Eveet, şimdi gelelim açıklama kısmına. Önce programın tam olarak ne yaptığını anlatayım daha sonra açıklamalara geçeriz. Program kullanıcının mac adresini sizin verdiğiniz KEY ile (burada "pythontr") bit kaydırma işlemine tabi tutup bir değişken üretiyor. Daha sonra sizin verdiğiniz değişken ile (şifrelenecek değişken) kendi ürettiği değişkeni xor işlemine sokup size şifrelenmiş veriyi döndürüyor.

Gelelim metodlara:

getMacAddress():

os ve sys modüllerini kullanarak kullanıcının mac adresini öğreniyoruz.

sys.platform ile kullanıcının işletim sistemini öğreniyoruz, burada winfos ve linux için düzenlenmiştir.

os.popen ile komut istemine bir boru açıp mac adres bilgilerini veren komutu çalıştırıyoruz, devamında ise string işlemlerle çıktıdan mac adresini ayıklıyoruz.

mixMac():

Burada aldığımız mac adresi ile belirlediğimiz KEY değişkenini bit kaydırma işlemi ile karıştırıyoruz ve bu karıştırdığımız yeni string veriyi döndürüyoruz. Burada dikkat edilecek önemli nokta verdiğiniz KEY'in mac adresinden uzun olmaması gerektiği. Aksi halde "string index out of bound" hatası alırsınız.

decrypt():

Bu fonksiyon ise şifresini çözdüğümüz veriden ham şifreyi elde etmeye yarıyor. Programın kullanımında da göreceğiz, 8 karakterli bir şifre verdiğinizi varsayalım, çözdüğünüz şifre mac adresinin karakter sayısı+verdiğiniz KEY'in karakter sayısı kadar tekrarlı gelecek. Bu yüzden şifreleme yaparken şifreli verinin sonuna şifrenin karakter sayısını giriyoruz ve bu fonksiyonda o karakter sayısı kadar veriyi çekip tekrarları almamış oluyoruz. Korkmayın aşağıda örnekleyince daha kolay anlayacaksınız :)

xor():

Esas oğlan. Şifreleme işlemini yapan fonksiyon. Yaptığı iş çok karışık değil aslında. Programa gönderdiğiniz şifre ile programın oluşturduğu verinin her bir karakterinin ASCII kodunu alıp onları xor işlemine sokuyor. Burada "encrypt" parametresinden bahsetmekte fayda var. Şifreleme yapacağımız zaman "True" çözümleme yapacağımız zaman "False" değeri veriyoruz. Onu şu sebepten kullandık, şifreleme sırasında şifrelediğimiz verinin karakter sayısını verinin sonuna eklediğimizi söylemiştik. Çözümleme yaparken referansımız olan mac adresi ile xor işlemine soktuğumuzda verideki karakter sayısının işlenmediğini görürüz, çünkü mac adresinin karakter sayısı aynıdır ancak biz şifreli veriye sonradan bir karakter eklemişizdir, dolayısıyla mac adresinde o karakter ile xor işlemine girecek eleman kalmamıştır. Bu yüzden çözümleme yapacağımız zaman mac adresine şifremizin eleman sayısını da işleme sokmak için bir veri ekliyoruz. Peki nedir eklediğimiz veri "\x00" verisi, yani ascii 0'ın char karşılığı. Peki neden 0 ekledik, 0 ile herhangi bir sayıyı xor işlemine sokarsanız sonuç olarak sayının kendisini alırsınız. Anlayacağınız 0 xor işlemi için etkisiz eleman, dolayısıyla bize direk olarak şifremizin karakter sayısını döndürüyor. Olay bundan ibaret, 2 tane integer değerin xor sonucunu veriyor bize (her karakter için). Şifrelenmiş verimiz bu oluyor.

Şimdi gelelim programın örnek kullanımına. Python yorumlayıcısını açıyoruz (yanında kahve içmekte özgürsünüz) ve başlıyoruz.


In [1]: from Encrypt import Encrypt
In [2]: e=Encrypt()
In [3]: passwd='adige'
In [4]: sifreli=e.xor(passwd)
In [5]: sifreli

Out[1]: 'Q\x14SUW[!-]]%T\x10]WS^,#_Y S\x13_SVS"![\\-W\r[V[] %^Q#&\x0e^[U_$ S_![\nSUW[!-]]%!\x1d]WS^,#_Y Z\x15_SVS"![\\-5'

In [6]: sifresiz=e.xor(sifreli,False)
In [7]: sifresiz

Out[2]: 'adigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadigeadi5'

In [8]: sifre=e.decrypt(sifresiz)
In [9]: sifre

Out[3]: 'adige'


Programın kullanımı bu şekilde. Kafanıza takılan bişey olursa sormaktan çekinmeyin.
Şimdilik benden bu kadar, bir sonraki Python macerasında görüşmek üzere.

Özgür kalın..

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

14 Eylül 2008 Pazar

Döngü Teknikleri

Python kullanırken işinize yarayacağını düşündüğüm bir kaç döngü örneğinden bahsedeceğim.
Fakat bunları teker teker açıklamak yerine örnekler üzerinden anlatmak daha kolay olacak. Eğer takıldığınız yer olursa yorum kısmında belirtirseniz ayrıca açıklayabilirim.

1)ITERITEMS()

In [36]: sozluk={"fenerbahce":"sarikanaryalar","galatasaray":"aslanlar","besiktas":"karakartal"}
In [37]: for i,j in sozluk.iteritems():
....: print i,j
....:
....:
fenerbahce sarikanaryalar
besiktas karakartal
galatasaray galatasaray


2)ENUMERATE

In [56]: for i,j in enumerate(sozluk):
....: print i,j
....:
....:
0 fenerbahce
1 besiktas
2 galatasaray


3)ZIP()

In [58]: cevaplar=["Fenerbahce","Semih Senturk","Volkan Demirel"]
In [59]: sorular= ["Sampiyon","Gol Kralı","KOVA!"]
In [60]: for i,j in zip(cevaplar,sorular):
....: print "%s kim? : %s" %(j,i)
....:
....:
Sampiyon kim? : Fenerbahce
Gol Kralı kim? : Semih Senturk
KOVA! kim? : Volkan Demirel

Görüldüğü gibi aslında pekte açıklamaya gerek olmayan koda bakınca rahatlıkla ne işe yaradığını anlayabileceğiniz örnekler vermeye çalıştım. Yine de anlamadığınız yerler olursa yorum yapmaktan çekinmeyin.

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.

11 Eylül 2008 Perşembe

String Methods

Not:[] içerisinde verilen parametreler isteğe bağlı olduğunu gösterir. Yani o parametreleri girmesek de fonksiyonumuz çalışır.

capitalize()
Bu fonksiyon stringimizin ilk harfini büyültmeye yarar.

In [3]: isim="deniz"
In [4]: isim.capitalize()
Out[4]: 'Deniz'


center()
Kullanımı center(genislik[doldurulacak karakter]) şeklindedir. Stringimizi belirttiğimiz genişlikte ortalar.

In [46]: isim="Deniz"
In [47]: isim.center(5)
Out[47]: 'Deniz'

Sanki hiç bir şey olmamışa benziyor ???
Birde sıradaki örneğimize bakalım.

In [48]: isim.center(10)
Out[48]: ' Deniz '

İlk örnekte zaten Deniz 5 karakterden oluştuğu için bize bir değişiklik yansımadı. Genişlik değerini belirtirken stringin uzunluğunuda dikkate almanızda fayda var.

Burda da isteğe bağlı parametre ile kullanalım. Kullanmadığımız taktirde ortalamak için boşluk karakteri kullanılıyor.

In [49]: isim.center(10,"-")
Out[49]: '--Deniz---'

count(karakter,[başlangıç[,bitiş])
Karakter veya karaterler ile aradığımız karakterden stringimiz içinde kaç adet olduğumu öğrenmeye yarar.

In [53]: isim2="Şemsi paşa pasajında bir şemsiyeci"
In [54]: isim2.count("paşa") #Pasajda kaç paşa olduğunu saydırıyoruz :)
Out[54]: 1
In [55]: isim2.count("i")
Out[55]: 4

In [61]: isim2.count("i",20,35) #20. karakterden 35. karaktere kadar kaç adet i harfi olduğunu sayıyor.
Out[61]: 2


endswith(karakter[baslangic[,bitis]])
Stringin karakter(ler) ile belirttiğimiz değerle bitip bitmediğini kontrol eder.

In [67]: isim2.endswith("yeci")
Out[67]: True
In [68]: isim2.endswith("yei")
Out[68]: False

Python 2.5 ile birlikte karakter yerine tüpte kullanabiliriz.

In [86]: import string
In [87]: cumle="Bu cumle noktalama isaretiyle mi biticek ?"
In [88]: noktalama=tuple(string.punctuation)
In [89]: cumle.endswith(noktalama)
Out[89]: True

Tüpler ile çalışma mantığı String tüpün içerisinde bulunan değerlerden herhangi biriyle mi bitiyor şeklindedir.

find(karakter[bas[,bitis]])
Stringimizin içinde karakterin olup olmadığını kontrol eder. Eğer var ise ilk bulduğunun indeksini döndürür. Yoksa -1.

In [115]: cumle="cumle icinde karakter ariyoruz"
In [116]: cumle.find("i")
Out[116]: 6
In [117]: cumle.find("kara")
Out[117]: 13
In [118]: cumle.find("p")
Out[118]: -1

islower(),isupper()
String içerisindeki tüm harflerin büyük ya da küçük olduğunu kontrol eder. Eğer bir tane bile küçük harf varsa False değeri döndürür.

In [124]: cumle
Out[124]: 'cumle icinde karakter ariyoruz'
In [125]: cumle.islower()
Out[125]: True
In [126]: cumle=cumle + "Buyuk harf ekledim bir tane"
In [127]: cumle
Out[127]: 'cumle icinde karakter ariyoruzBuyuk harf ekledim bir tane'
In [128]: cumle.islower()
Out[128]: False

isdigit()
Karakterlerin sayisal olup olmadığını kontrol eder. Birisi bile sayisal değilse False değeri döndürür.

In [130]: cumle = "1453 4151 15151251 1"
In [131]: cumle.isdigit()
Out[131]: False
In [132]: cumle = "14534151151512511"
In [133]: cumle.isdigit()
Out[133]: True

join(seri)
Biraz yaratıcılıkla beraber çok fazla işinize yarayacak bir fonksiyon.
Anlamak için örnekleri inceleyip kendinizde bir kaç deneme yapınız.

In [170]: c="Python ogreniyorum"
In [171]: d=c.join("''")
In [172]: print d
'Python ogreniyorum'

Yukarıda ki örnekteki gibi kullanım pek fazla olmamaktadır. Fakat sıradaki örnek çok işinize yarayabilir.

In [183]: isimler
Out[183]: ['deniz', 'gokmen', 'mirat', 'huseyin']
In [184]: " ".join(isimler)
Out[184]: 'deniz gokmen mirat huseyin'

In [185]: ";".join(isimler)
Out[185]: 'deniz;gokmen;mirat;huseyin'
In [186]: "-".join(isimler)
Out[186]: 'deniz-gokmen-mirat-huseyin'


lower(),upper()
Stringin içindeki tüm karakterleri büyültmeye ve küçültmeye yarar.

In [191]: cumle="BUYUK HarFLerDEN OluSaN Bir cUmlE"
In [192]: cumle.lower()
Out[192]: 'buyuk harflerden olusan bir cumle'
In [193]: cumle.upper()
Out[193]: 'BUYUK HARFLERDEN OLUSAN BIR CUMLE'


strip(),lstrip(),rstript()
strip() fonksiyonu string içerisinde sağdan ve soldan istediğimiz karakterleri çıkartmaya yarar. Eğer parantez içerisinde bir değer belirtilmemişse boşlukları çıkartır. Aşağıda ki örnekleri iyice inceleyip ne olup bittiğini anlamaya çalışın.

In [202]: 'www.python.com'.strip('cmow')
Out[202]: '.python.'
In [203]: 'www.python.com'.strip('cmow.')
Out[203]: 'python'

In [204]: 'www.python.com'.strip('cmow.n')
Out[204]: 'pyth' #"n" karakterini ekleyince "o" nunda gittiğine dikkat ediniz.

In [205]: 'www.python.com'.strip('cmowp.n')
Out[205]: 'yth'

In [206]: 'www.python.com'.strip('cmop.n')
Out[206]: 'www.pyth' #"w" silinince baştan bir eksiltme yapmadığına dikkat ediniz.


Şimdide lstrip ve rstrip kullanımına 2 örnek

In [208]: 'www.python.com'.lstrip('.w')
Out[208]: 'python.com'

In [209]: 'www.python.com'.rstrip('.omc')
Out[209]: 'www.python'

replace(eski,yeni[,sira])
String içerisindeki değeri değiştirmek için kullanırız. eski ile verilen karakterleri yeni ile değiştirir.

In [210]: a='www.python.com'

In [211]: a.replace('w','v')
Out[211]: 'vvv.python.com'

In [212]: a.replace('w','v',2)
Out[212]: 'vvw.python.com'

In [213]: a.replace('y','i')
Out[213]: 'www.pithon.com'

In [215]: a.replace('yth','it')
Out[215]: 'www.piton.com'


Sık kullanılan bazı string methodlarını elimden geldiğince anlatmaya çalıştım. Methodlar hakkında ayrıntılı bilgi için "print string.method.__doc__" (örn: print a.replace.__doc__) burada anlatılmayan diğer string methodları için burayı ziyaret edebilirsiniz.