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 ;)

25 Eylül 2008 Perşembe

Django ile Anket 2

Kaldığımız yerden devam edelim. Şimdi admin panelini kullanarak iki anket ekleyin.
Ben anket sorusu olarak "Hangi editörü kullanıyorsunuz ? " ve "Günde kaç saat bilgisayar başındasınız ?"'ı ekledim.
Ardından anasayfadan Anket bölümüne tekrar geldiğinizde eklediğimiz anketlerin listelendiğini göreceksiniz.

Sanırım hepiniz tuhaf giden birşeyler olduğunu fark etmişsinizdir. Tüm anketler "Anket object" ismiyle yani ne olduğunu anlayamadığımız bir isimle listelenmekte. Gelin bunu rahat anlaşılabilir bir hale nasıl sokabiliriz onu inceleyelim.

Bunun için models.py dosyamızdaki sınıflarımızın altına şu satırları ekliyoruz.

def __unicode__(self):
return self.soru


Bunu anket sınıfının altına ekliyoruz. Burada verdiğimiz self.soru veritabanında ki kaydımızın ismi.


def __unicode__(self):
return self.secim

Bunu da Secim sınıfına ekliyoruz.

Şimdi admin panelini güncelleyip nasıl göründüğüne bir bakalım. Sanırım bu hali daha açıklayıcı olmuştur ;)

Şimdi de alanların yerlerini değiştirelim. Şu anda bir anket eklerken ilk sırada soru 2. sırada da yayin tarihi bulunuyor. Şimdi bunların yerlerini değiştirelim. Anket dizini içerisindeki admin.py dosyasında admin.site.register() yerine aşağıdaki satırları ekleyin.

class AnketAdmin(admin.ModelAdmin):
fields = ['yayin_tarihi','soru']

admin.site.register(Anket,AnketAdmin)

Değiştirdikte ne oldu yani şimdi ? dediğinizi duyar gibi oluyorum :) Anket uygulaması gibi 2 alandan oluşan bir uygulamada pek bir işe yaramaz ama alan sayısı arttıkça sıralamanın istediğini gibi olmasını isteyebilirsiniz. Ya da sık kullanılmayan bazı alanları gizlemek ya da benzer kategorileri gruplandırmak. Şimdi bunlara da birer örnek verelim. İhtiyacınız olduğunda bu da varmış diye aklınızda bulunsun ;) Yine admin.py dosyasında ki AnketAdmin clasını değiştiriyoruz.

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi']}),
]

Bu değişiklikle Yayin Tarihi bilgileri ayrı bir bölümde Tarih Bilgileri başlığıyla gösterilecek. Tarayıcımıza gidip hemen bir kontrol edelim.

Ardından da ufak bir değişiklik daha yapalım.

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi'],'classes': ['collapse']}),
]


Neyse bu kadar ince ayar yeter. Biz anketimize geri dönelim. Anketi hazırladık fakat sorular yok. Hemen sorularıda admin paneline tanıtalım. Bunun nasıl yapıldığını daha önce görmüştük. admin.py dosyasını açıyoruz tekrar.

admin.site.register(Secim)

Satırını ekliyoruz.

Ardından Secimleri seçip bir kaç seçenek ekleyelim ki anketimiz şenlensin ;)
Yeni seçenek eklerken yukarıdan hangi ankete ekleyeceğimiz seçiyoruz. Fakat önce soruyu ekle sonra seçenekleri ekle falan bana pek kullanışlı gelmiyor. Eğer sizde benim gibi düşünüyorsanız birde şunu deneyin.

Az önce eklediğimiz satırı kaldırıp AnketAdmin sınıfının sonuna inlines = [Secimler] i ekliyoruz. Yani dosyamızın son hali şuna benzeyecek.

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


class Secimler(admin.StackedInline):
model = Secim
extra = 4

class AnketAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['soru']}),
('Tarih Bilgileri', {'fields': ['yayin_tarihi'],'classes': ['collapse']}),
]
inlines = [Secimler]

admin.site.register(Anket,AnketAdmin)

Yeniden bir kayıt girmeyi deneyin ya da girdiğiniz kayıtları düzenleyin.
Birde Secimler(admin.StackedInline) yerine admin.TabularInline şeklinde kaydedip deneyin. Hangisi daha hoş ?

Ekleme bölümünü baya bir kurcaladık. Sıra geldi değişiklik bölümüne, Anketler-Değiştire geldiğinizde sadece anketin ismini görebiliyorsunuz. Şimdi biraz daha ayrıntı ekleyelim. inlines seçeneğinde yaptığımız gibi bir değişiklik yapacağız. admin.py dosyasında AnketAdmin sınıfı altına şu satırı ekleyelim.

list_display = ('soru','yayin_tarihi')

Şimdi sayfamızı yenileyelim. Ardından az önceki örnekte olduğu gibi aşağıdaki satırlarıda tek tek(!) ekleyerek her birinin neler yaptığını anlamaya çalışın.

list_filter = ['yayin_tarihi']
search_fields= ['soru']
date_hierarchy = 'yayin_tarihi'

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

15 Eylül 2008 Pazartesi

siteler üzerinde urlgrabber ile gezinti işlemi

Zaman zaman web sitelerine veri gönderip, dönen sonuçlara göre otomatik işlemler yazan kodlar yazmamız gerekebilir. bu iş için, hangi dili kullanıyorsak kullanalım bir HTTP kütüphanesine ihtiyaç duyarız. python bize bu konuda bir çok seçenek sunuyor. urllib, httplib, urlgrabber, pycurl gibi bu işi gayet güzel yapan HTTP modülleri kullanımımıza amade..

Ben kısaca, urlgrabber modulünden bahsedeceğim yazı boyunca. urlgrabber, urllib2 kütüphanesinin daha kullanıcı-dostu şekilde düzenlenmiş ve salt python ile yazılmış hali. yapmak istediğiniz işlemleri daha basitçe ve hızlı bir şekilde yapabiliyorsunuz. klasik olarak ilk önce, "pythontr.blogspot.com" adresine GET isteğinde bulunup kaynak kodlarını alalım:


from urlgrabber import urlopen

pytr = urlopen("http://pythontr.blogspot.com")
veri = pytr.read()
pytr.close()

print veri


kodu çalıştırdığınızda bloğumuzun HTML kaynak kodları ekrana basılacaktır. biraz daha pythonic yazarsak;

from urlgrabber import urlopen
print urlopen("http://pythontr.blogspot.com").read()


basit bir GET isteğinden sonra artık, daha komplike işlemlere geçelim. eğer istek yapacağımız sayfaya sağlıklı bir şekilde girebilmek için çerez yollamamız gerekiyorsa, HTTP_USER_AGENT değiştirmeliysek, ya da başka bir HTTP başlığı değiştirmek istersek ne yapmalıyız?

urlgrabber, bu konuda çok fazla seçenek sunuyor. örneğin HTTP_USER_AGENT bilgisini değiştirmek istediğimizi düşünelim;

from urlgrabber.grabber import URLGrabber

istek = URLGrabber(user_agent = 'pythontr python bot')
sonuc = istek.urlopen("http://pythontr.blogspot.com").read()


sadece 1 parametre eklemiş olmamız yetti. diğer parametrelere bu adresten göz atabilirsiniz.

örnek uygulama

python-challenge.com adresinde python programcılarının pratik yapmaları için seviyelerle hazırlanmış bir site var. python ile ipuçlarını yorumlayıp çözüme ulaşıyorsunuz. o siteden 4.seviyeye bakıyoruz hemen. gördüğünüz üzere. bağlantılara tıklasak bile bir sonuç alamıyoruz, tekrardan başka random bir sayı çıkıyor. anlıyoruz ki, bu işi elle yapmak yorucu olacak.

python ile her seferinde gördüğü bağlantıya istek yapan, gelen sayfaya aynı şekilde bir bağlantı daha varsa yine istek yapan ama yoksa durup, URL adresini veren bir uygulama yapalım. uygulama hem çerez yollasın, hemde regex ile değişiklik var mı yok mu kontrol etsin, duruma göre işlemi durdurup devam edeceğine karar versin.

from urlgrabber.grabber import URLGrabber
import re

def istekYap(sonGelen):
istek = URLGrabber(http_headers = (('info', 'you+should+have+followed+busynothing...'),))
sonuc =istek.urlopen("http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="+sonGelen).read()
try:
yeni = re.search("and the next nothing is ([0-9]{1,5})", sonuc).group(1)
print "%s rakami bulundu, yeni istek yapiliyor." % yeni
istekYap(yeni)
except:
print "son uygun rakam: " + sonGelen

istekYap("12345")

özyinelemeli çalışan bu fonksiyon ile, yüzlerce istekten sonra gerçek adrese ulaşıyorsunuz :)

dip notlar

http://linux.duke.edu/projects/urlgrabber/comparison.ptml
http://linux.duke.edu/projects/urlgrabber/help/urlgrabber.grabber.html
http://linux.duke.edu/projects/urlgrabber/examples.ptml

14 Eylül 2008 Pazar

Merhaba dünya ile başladı herşey..

Bu yazımız ile birlikte Python ile mobil programlamaya girmiş bulunuyoruz, hepimize hayırlı uğurlu olsun.

Her programlama dilinin girişinde "Tüm programlama dillerinde olduğu gibi öncelikle merhaba dünya örneği ile başlayacağız.." gibi klasik bir giriş yapmayacağım. Merhaba dünya o kadar basit bir anlam içermiyor çünkü. Daha kozmik (kozmikte neyse!) bir yapısı olduğunu düşünüyorum. Hatta bunun çook öncelere, Hz. Adem'e dayandığı ile ilgili düşüncelerim var. Hz. Adem cennetten kovulup dünyaya gönderildiğinde "merhaba dünya" repliği ile başlamadığını kim söyleyebilir?

Olayı esrarengizleştirme çalışmalarımdan sonra dikkatinizi yeterince celbettiğimi umarak konuya giriyorum.


print "merhaba dunya"


En basit haliyle bu, telefonunuza kurduğunuz pythonun etkileşimli konsolunda bu kodu yazıp çalıştırırsanız aynı ekranda çıktıyı görebilirsiniz.

Şimdi biraz daha süsleyelim.


import appuifw
appuifw.note(u"merhaba dunya","conf")

Burada ileriki bölümlerde de sık sık kullancağımız appuifw modülünü import ediyoruz önce. Bu modülden biraz bahsetmekte fayda var. Açılımı "application user interface framework". Buradan da anlaşıldığı gibi pyS60 içerisinde kullanacağımız görsel bütün elemanlar bu modül içerisinde bulunmaktadır.

"appuifw.note" ile kullanıcıya bilgilendirme-uyarı-hata durumlarını ilettiğimiz pencereyi oluşturuyor.

Kullanımı: appuifw.note("mesaj", "mesajın türü")

Mesaj kısmına girdiğimiz u"merhaba dunya" daki "u" ise ondan sonra girdiğimiz verinin bir Unicode String olduğunu programa belirtmektedir. Program içerisinde kullanacağımız stringlerden önce onu kullanmamız gerekecek.
Mesajın türü olarak belirttiğimiz "conf" confirmation'ın kısaltmasıdır. Kullanılabiliecek diğer parametreler "error" ve "info" dur.

Eveet, olayı biraz daha karmaşıklaştırmanın zamanı geldi sanırım. Şimdi kullanıcıdan ismini alalım ve ekrana "merhaba blabla" ile onu selamlayalım. Hızlı gitmiyoruz değil mi :)


import appuifw
isim=appuifw.query(u"Adınızı Giriniz:","text")
appuifw.note(u"Merhaba "+isim,"conf")


Yeni bir şey daha kullandık. Öncelikle kullanımına bir bakalım.

appuifw.query("başlık","içeriğin türü","ilk değer")

query kullanıcıdan veri almak için kullandığımız bir eleman. Aldığı parametrelere bakarsak, "başlık" veri kutusunun üzerinde görünecek, kullanıcıya ne gireceği hakkında bilgi verdiğimiz değişkendir. "içeriğin türü" ise kullanıcının veri kutusuna ne tür bir veri gireceğini belirttiğimiz yerdir. Alabileceği diğer parametreler "number,date,time,code,query,float". "ilk değer" ile belirttiğimiz ise veri kutusunun içerisinde başlangıçta bulunmasını istediğimiz veridir, opsiyoneldir, herhangi bir değer verlimezse veri kutusu boş olarak görüntülenir.

Başlangıç için bu kadar yeterli sanıyorum. Diğer programlarımızda burada yer vermediğim görsel elemanları da kullanacağız. Hepsini ayrıntılı şekilde anlatmayacağım, program içerisinde nasıl kullanıldıkları rahatlıkla anlaşılabilmekte. Ayrıca pyS60 için özelleştirilmiş diğer modüllerin kullanımına da değineceğim. Devamını takip etmeniz için ağzınızı sulandırma çalışmalarımdan sonra veda vakti geldi sanıyorum.

Kalın sağlıcakla..

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

Django Notları - 3

Django'da şablon kavramını anlatmadan önce, şablondan ne anlamamız gerektiği konusunu belirginleştirelim. Örneğin, cep telefonlarımızda hazır mesajlar yazıp kaydedebiliyoruz veya daha önce kaydedilmiş olanları gerektiğinde kullanabiliyoruz. "İşteyim, döneceğim", "Beni 10 dakika sonra ara." gibi bence gereksiz olan bu hazır mesajlar şablon diye geçiyor.

Ama Django'daki şablonlarımız, projemizin çok önemli bir parçası olarak karşımıza çıkıyor. Bir veya birkaç değişkene, bütün veya parça halinde html kodlarını yazmak; tanımladığımız fonksiyonları o değişkene çağırmak ve bu kodu yorumlatmak, kodu hem çirkinleştirecek; hem de projenin gelişimini çok zorlaştıracaktır.

Şimdi saat bilgilerini ekrana yazdırdığımız fonksiyonun kodlarını ve urls.py dosya içeriğini tekrar verelim. views.py dosyamız:

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

from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>Saat ve tarih bilgisi: %s.</body></html>" % now
return HttpResponse(html)


urls.py dosyamız:

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

from django.conf.urls.defaults import *
from mysite.views import current_datetime

urlpatterns = patterns('',
(r'^time/$', current_datetime),
)



Burada html değişkenine atadığımız html kodu kısa:

<html><body>Saat ve tarih bilgisi: %s.</body></html>

Şimdi bu kodu, html uzantılı olarak ayrı bir yere kaydedelim:

<html>
<head>
<title>Merhaba Django!</title>
<style>

body {background-color: #aaa}
p {font-size: 12px}
</style>
</head>
<body>
<p>Cancanlı django'muzla zaman bilgilerimizi öğrenelim: {{ zaman }}</p>
</body>

</html>


Birşey dikkatınızı çekti mi? {{ zaman }} diye birşey yazdık, nedir o? Hayır, html ile ilgili bir özellik değil. Şimdi proje dizinimizde templates diye bir alt dizin oluşturalım ve bu kodu zaman.html olarak, bu alt dizinin içine kaydedelim. Sıra geldi, Django'muza şablon dizinimizin nerede olduğunu tanımlamaya. settings.py dosyasını açın ve şu satırları bulun:

[...]

ROOT_URLCONF = 'negzelfoundation.urls'

TEMPLATE_DIRS = (
)

[...]


TEMPLATE_DIRS tüpüne, templates dizinimizi eleman olarak yazmamız gerekiyor. Burada python bilgilerinizi istediğiniz gibi kullanabilirsiniz. İsterseniz, os.path modülünü çağırıp yapabilirsiniz, şu şekilde:

[...]
import os.path

[...]
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
[...]


replace'in ne işe yaradığını umarım biliyorsunuzdur. Posix standardındaki işletim sistemlerinde sanırım ona gerek yok. Ama siz de benim gibi, bunun için os.path import etmeye gerek yok derseniz, şu şekilde de templates dizinini Django'ya göstertebilirsiniz:

[...]
ROOT_PATH = "/proje/dizin/yolunu/buraya/yazin"

[...]
TEMPLATE_DIRS = (
'%s/templates' % ROOT_PATH,
)
[...]


Buraya kadar tamam; ama hala {{ zaman }}'ın ne olduğunu hala söylemedik. Şimdi views.py dosyasındaki current_datetime fonksiyonunu, gerekli modülleri çağırıp tekrar tanımlayalım:

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

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
t = get_template('zaman.html')
c = Context({'zaman': now},)

html = t.render(c)
return HttpResponse(html)


get_template, şablonu çağırmak için; Context ise, fonksiyonda tanımladığımız değişkenleri, şablonumuzdaki {{ zaman }} gibi ifadelere bağlamamız için çağrıldı. Sonra, html değişkeninde bağlamları şablonda çevirtip, bir sonraki satırda da bu değişkeni döndürüyoruz. Bakalım nasıl dönmüş:

Cancanlı Django'da Zaman

Huh, iyi eğleniyoruz ;-).

Şablonlarda Etiketler



Örnek olarak oluşturduğumuz zaman.html şablosunda bildiğiniz gibi css, javascript ve html kodlaması yapabilirsiniz. Fakat zaman zaman PHP'de olduğu gibi, belli bir şarta bağlı olarak tekrar edilmesi istenen veya koşulun yerine getirilip getirilmediğine göre değişen fonksiyon cevapları ihtiyacı duyabiliriz:

[...]
<ul>
{% hede fonksiyonu tamamlandığı sürece %}
<li>{{ hede }}</li>
{% döngü sonu %}
</ul>
[...]


Şimdi şöyle bir örnek yapalım. Üç satırlık bir liste oluşturalım, ilk satırda şuanki saat, bir sonrakinde bir saat sonraki saat, ondan sonrakinde de iki saat sonraki saati yazdıralım. İlk olarak, views.py dosyamızda bizim için gerekli modülleri çağıralım:

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

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime


clock_list isimli fonksiyonumuzu oluşturalım. Örneğimiz için sadece saat bilgisini almak bizim için yeterli:

def clock_list(request):
time = int(datetime.datetime.now().hour)


Sonra, fazla kafamızı bulandırmadan; şimdilik neden, niçin demeden, sonradan oluşturacağımız saat.html isimli şablonu çağırıp, saat değişkenimizi (time) şablona gömerek sayfayı döndürelim:

def clock_list(request):
time = int(datetime.datetime.now().hour)
time_list = []
phrase_list = []
for x in range(3):
time_list.append(time + x)
phrase_list.append("%s saat sonra, akrep %s gösterecek." % (x, time_list[x]))

t = get_template('saat.html')
c = Context({'phrases': phrase_list},)
html = t.render(c)
return HttpResponse(html)



Evet. Ama daha saat.html isimli örnek şablonumuzu oluşturmadık. Örnek olarak yazım templates dizinine alalım:


<html>
<head>
<title>Merhaba Django!</title>

<style type="text/css">
body {background-color: #e0ffb8}
ul {border: 1px solid #333; padding: 0}
li {border: 1px solid #aaa; list-style-type: none}
</style>
</head>
<body>
<center>

<ul>
{% for phrase in phrases %}
<li>{{ phrase }}</li>
{% endfor %}
</ul>
</center>
</body>

</html>


<ul> tagı içinde bi for döngüsü yazmışız, farkettiniz mi? views.py'de tanımladığımız clock_table fonksiyonumuzda oluşturulan listenin her bir elemanı için ekrana bir liste elemanı yazdırıyoruz. Üç adet liste için belki değmez, belki de statik sonuçlar için bu kadar atraksiyonu gereksiz bulabiliriz; fakat sonucu değişebilecek, 100 maddelik bir listeyi yazmayı pek göze alacak değiliz, biz pratik programcılar için..

Evet, saat.html dosyamız da hazır. Son olarak bu fonksiyonu bir sayfaya atayalım. urls.py'yi düzenliyoruz:


from django.conf.urls.defaults import *
from mysite.views import clock_list, current_datetime, hours_ahead

urlpatterns = patterns('',
(r'^clocks/$', clock_list),
(r'^time/$', current_datetime),
(r'^time/artir/(\d{1,2})/$', hours_ahead),
)


Nereye atamışız? http://adresimiz/clocks/ sayfasına.. python manage.py runserver ile sanal sunucumuzu çalıştırıp http://127.0.0.1:8000/clocks/ adresinden bir bakalım nasıl olmuş:

Saat Listesi

Eh, bu da fena değil. Biz burada döngülerin nasıl kullanılacağı üzerine, for ile bir örnek göstererek öğrenmiş olduk. if'tir, else'tir, ifequal ve benzeri diğer döngülerdir, bunların hepsi aynı mantıkla yazılıp kullanılmaktadır. Bu konuda teker teker örnek vermek yerine, şu1 linkteki kodları incelemeniz, sizin için fazlasıyla yeterli olacaktır. Eğer yine de değinilmesini istediğiniz önemli bir nokta varsa, bunu bize bildirmekten çekinmeyin.

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.

9 Eylül 2008 Salı

Django Notları - 2

Bir içerik düşünün, bulunduğunuz sayfanın linki ile ilişkilendirilmiş. Çağrılan sayfanın adresine göre, tanımladığınız fonksiyonları kullanmak, o sayfada görüntülemek istiyorsunuz. Peki bunu nasıl yapabiliriz? Önceki örneğimizde, fonksiyonlarımızı nerede tanımlayıp (views.py), adresleri nerede tanımlayacağımızı (urls.py) öğrenmiş olduk. Bu araçları kullanarak, web tarayıcımızda zaman bilgilerini göstermeyi başardık.

Şimdiki örneğimiz ise, dinamik internet sayfalarını nasıl oluşturacağımız ile ilgili. Amacımız basit; adresteki dizin numarasıyla sayfamızdaki saat bilgisini ilişkilendirmek; yani dizin numarası kaçsa, sayfamız da o kadar saat ileriyi gösterecek. İşte, views.py'deki zaman fonksiyonumuz:

def hours_ahead(request, offset):
offset = int(offset)
dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
html = "<html><body>%s saat sonra zaman şöyle olacak: %s.</body></html>" % (offset, dt)
return HttpResponse(html)


Evet, bu kodu views.py dosyasına aynen yazıyoruz. Fonksiyonun amacı gayet basit. dt isimli değişken, sayfa adresindeki dizin numarası değerini alıyor ve o integer olarak belirlenmiş değeri saat değişkenine ekliyor. Şimdi urls.py'ye dönelim:


from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead

urlpatterns = patterns('',
(r'^time/$', current_datetime),
(r'^time/artir/(\d{1,2})/$', hours_ahead),
)


mysite dizinindeki views.py dosyasında tanımladığımız current_datetime fonksiyonunu çağırdığımız gibi, hours_ahead'ı da çağırdık ve urlpatterns'te, fonksiyonumuzun çalışacağı sayfayı tanımladık. Fakat dikkat edin, sayfa adresimiz tam belli bir sayfayı belirtmiyor:
(r'^time/artir/(\d{1,2})/$', hours_ahead),

Sayfa adresindeki numaraya dikkat

Düzenli İfadeler


Son yazdığımız kodda, (\d{1,2}) ifadesinin ne anlama geldiğini söyleyeyim. Bu bir düzenli ifadedir. Yani biz burada "\d" kullanarak değerin sayı olduğunu, {1,2} ile de değerin 1, 2 veya bunların arasında bir değer olduğunu belirtmiş olduk. İnternette "regular expressions programming" şeklinde araştırma yaparsanız, bir çok kaynak bulabilirsiniz.

urls.py'de kullanabileceğiniz belli başlı düzenli ifadeleri bir tabloyla gösterelim:

Editörün notu : Bu bölümü ayırdım. Buradan bulabilirsiniz.

Şimdi örneğimize geri dönelim. urls.py dosyasında belirtmiştik ki, sayfa adresinde 1 ve 2 basamaklı sayılar views.py'de tanımlanan hours_ahead fonksiyonumuzla ilişkilendirilsin. Fonksiyonun amacı neydi? Sayfa adresinde belirtilen değeri şuanki saate eklemek. Eğer urls.py'de belirtilen 1 ve 2 basamaklı değerlerin dışında bir sayı girersek ne olur peki? Deneyelim:

Sayfa Bulunamadı!

Bu sayfanın tasarımı bile harika..

Düzenli İfadelelerde Kullanılan Karakterler

"."
Nokta, normal modda iken yeni satır karakteri hariç herhangi bir karakter demektir.

"^"
Çıkma işareti, karakter katarının başlangıcını eşleştirmeye çalışır.

"$"
Dolar işareti, metnin sonunu veya metin birden fazla satırdan oluşuyorsa yeni satır karakterinden önceki bölümü eşleştirmeye çalışır.

"*"
kendisinden önce gelen karakterin (ya da grubun) 0 yada daha çok kere tekrarlandığını anlatır.

"+"
kendisinden önce gelen karakterin (ya da grubun) 1 ya da daha çok kere tekrarlandığını anlatır.

"?"
kendisinden önce gelen karakterin (ya da grubun) 0 ya da 1 kere tekrarlandığını anlatır.

"{sayı}"
kendisinden önce gelen karakterin (ya da grubun) sayı kere tekrarlandığını anlatır.

"{sayı1,sayı2}"
kendisinden önce gelen karakterin (ya da gurubun sayı1 den sayı2 ye kadar kere tekrarlanacağını anlatır.)

8 Eylül 2008 Pazartesi

PyS60 Kurulumu

Öncelikle telefonunuzun hangi nesil olduğunu öğrenmeniz gerekiyor. Şu adresten öğrenebilirsiniz. Developer Platform başlığından telefonunuzun hangi nesil olduğunu ve özellik paketini öğrendikten sonra bu adresten python yourmlayıcısını ve yorumlayıcı arayüz dosyalarını indirmeniz gerekli.
Bir örnekle anlatırsak daha açıklayıcı olur diye düşünüyorum.Telefonumun özellikleri: 2nd Edition Feature Pack 2 olsun.

İndireceğim dosyalar:
PythonForS60_1_4_1_2ndEdFP2.SIS
PythonScriptShell_1_4_1_2ndEdFP2.SIS

Bu dosyaları telefonunuza gönderip kurduktan sonra ana menünüze Python simgesinin yerleştiğini göreceksiniz.
Programı çalıştırdığınızda menüden Interactive Console‘u seçip etkileşimli yorumlayıcı ile python kodu yazabilirsiniz, daha önce kaydettiğiniz python kodlarını çalıştırmak istiyorsanız Run Python Script menü elemanını seçebilirsiniz.
Fırsat buldukça üzerinde çalıştığım örnek programları buradan sizlerle paylaşacağım.Kalın sağlıcakla.

6 Eylül 2008 Cumartesi

Python ve MySQLdb Eşliğinde pisi.api

Özgürlük İçin için tüm app:gui (kullanıcı arayüzüne sahip) olan paketlerin listesi gerekti. Bu iş için ufak bir kod yazdım (Uğur Çetin ve Faik Uygur'un katkılarıyla) ve bu kodu sizinle paylaşmak istedim.

Bu işi PiSi API ile yapacağız. PiSi API ile aldığımız paketleri ufak bir kontrolden sonra MySQL veritabanına ekleyeceğiz. Bu yüzden öncelikle pisi ve MySQLdb yi import edelim;

import pisi
import MySQLdb

Veritabanı bağlantımızı sağlayalım

conn = MySQLdb.connect (
host = "localhost",
user = "root",
passwd = "",
db = "oi"
)
cursor = conn.cursor()

Sonra paket bilgilerini alabilmek için kullanacağımız fonk

packagedb = pisi.db.packagedb.PackageDB()

Paketin app:gui olup olmadığını kontrol edelim ve eğer app:gui ise ve daha önceden veritabanına eklenmediyse paketi veritabanımıza ekleyelim.

for pkg in pisi.api.list_available():
if 'app:gui' in packagedb.get_package(pkg).isA:
cursor.execute("SELECT id FROM ideas_related WHERE name='%s'" % pkg)
row = cursor.fetchone()
if row == None:
cursor.execute("INSERT INTO ideas_related (category_id, name) VALUES ('3', '%s')" % pkg)
print "%s paketi veritabanına eklendi." % pkg


Bu küçük örnekte Python, PiSi API ve MySQLdb ile bir şeyler yaptık. Umarım birilerinin işine yarar.

Django Notları - 1

Girizgah


Merhabalar. Bu belge, Django'yu öğrenirken DjangoBook1 sitesinden aldığım, biriktirdiğim notlardan oluşmuştur. Belgenin tamamen kusursuz olduğu veya anlatımının çok iyi olduğu konusunda bir garanti vermiyorum; fakat yine de size yardımcı olabilecek notlar bulabileceğinizi umuyorum. Ayrıca, belge ile ilgili bir yanlışlık veya anlatmamı istediğiniz bir nokta olursa, eposta adresimi kullanarak benimle iletişime geçebilirsiniz:

Not:Django'nun ne olduğu, neden onu seçmemiz gerektiği; bu projenin hangi amaçla ortaya çıkarıldığı ve gelişimi hakkında bilgiler, belgeyi kısa tutmak için verilmemiştir. İnternet zengin bir okyanus :-)

Django'ya Başlamak


Çok değil, Şubat 2007'den beri GNU / Linux kullanıyorum ve onu kullanmaya başlamakla programlamaya ilgim hemen hemen aynı zamanlara denk geliyor. İnternet sitesi tasarımlarına ve programlamasına ilgi duyduğum için ilk olarak PHP'ye yönelmiştim ve hiçbir şekilde framework'un ne anlama geldiğini, ne işe yaradığını çözemememiştim. Hatta bir ara framework ile kastedilen şeyin Wordpress, Joomla ve benzeri şeyler olduğunu zannederdim (belki onlara da framework deniliyor olabilir). İngilizce sözlüğe baktığım zaman karşıma çıkan Türkçe anlamları da beni bir o kadar çıldırtmaya yeterdi: Çatı, çerçeve, web çatısı, web framework.. Yeni başlayan, tecrübesiz kişiler için bu sözcükler gerçekten bir anlam ifade etmiyor.
Sonra, güzel bir deneyim yaşadım. Ben yapacağım her site için tekrar tekrar açıp kodlara bakmak durumunda mıyım? Örneğin, alt tarafı sitenin ana sayfasında bir yazı göstermek için her defasında kodlarla cebelleşmek ne kadar akla mantığa uygundur? Üstelik zaman kavramı da hayatımızın her alanında olduğu gibi, programlamada da son derece önemli, sizce de öyle değil mi? Sıfırdan site yapmak yerine Joomla kuralım, temasını biraz değiştiririz, hazır site kalıbından çıkarmak da çok zor bir şey olmasa gerek hem, öyle değil mi?
Nitekim, nasıl ki kaslarımızı amacı doğrultusunda daha rahat kullanabilmek için kemiklere ihtiyaç duyuyorsak, yapacağımız siteler için de güzel bir altyapıya ihtiyaç duymamız olası, hele ki Python'da. İşte, buna framework deniyor. Düşünün, bir forum veya portal site yapacaksınız. Ama yönetim arayüzü yok :-). Ya da hiç düşünmeyin, hemen Django'yu kullanabilmemiz için neler gerekiyor, ona bakalım.

Django İçin Gerekli Programlar


Kullandığınız dağıtım veya işletim sistemine göre kurulumları değişeceği için, nasıl kurulacağını burada anlatamayacağım. Basit bir araştırma yeter diye umuyorum.
  1. Python
  2. Django
  3. Veritabanı tercihinize göre, Python'a veritabanı desteği:
    • Mysql
    • PostgreSQL
    • Sqlite

Not: Dipnotlarda verilen linkleri kullanmadan önce Paket Yönetici'nizde araştırma yapınız. Tek başlarına çalışmamakla birlikte, birkaç bağımlılığa da ihtiyaç duymaktadırlar. Örneğin python-mysql'in MySQL'a ihtiyaç duyması gibi.

Nihayet Projemizi Başlatıyoruz


Django için gerekli paketler kurulduktan sonra, projenizi barındırabileceğiniz uygun bir dizinde ilk olarak şu komutu veriyoruz:

gkmngrgn ~/programming $ django-admin.py startproject mysite

Böylece mysite dizinimiz ve dizin içinde de proje için gerekli dosyalarımız oluşturulacak:

mysite/
__init__.py
manage.py
settings.py
urls.py


Projemiz ile ilgili yapacağımız tüm işlemler, oluşturduğumuz mysite isimli dizinimizde yapılacak. Diyelim önemli değişiklikler yaptınız ve sitenizi web tarayıcınız ile kontrol etmek istiyorsunuz. O zaman mysite dizinimizde şu komutu vermeniz gerekir:

gkmngrgn ~/programming/mysite $ python manage.py runserver
Validating models...
0 errors found.

Django version 1.0, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.


Evet, komutun çıktısında da görebileceğiniz gibi, sitenizi http://127.0.0.1:8000/ adresinden kontrol edebilirsiniz. İşlemi sonlandırmak için CONTROL-C tuş kombinasyonunu kullanmanız yeterli. İsterseniz, sonraki adıma geçmeden önce bir bakalım, localhost'tan nasıl görünüyor?

ss

Çok tatlı, öyle değil mi? Şimdi proje dizinimizde (mysite) views.py isminde bir dosya oluşturup, örnek olarak şunları yazalım, açıklama satırlarını (en baştaki hariç, diğer "#" ile başlayan satırlar) yazmasanız da olur:

# -*- coding: utf-8 -*-
# Önce Türkçe karakter desteğimiz için utf-8'i yazdık.
# Şimdi gerekli modülleri çağıralım.
from django.http import HttpResponse
import datetime

# Sonra da datetime ile saat & tarih bilgilerini alarak HttpResponse'u döndürelim.
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>Saat ve tarihimizi, python modülü kullanarak yazdırdık: %s.</body></html>" % now
return HttpResponse(html)


Proje dizinimizdeki var olan örnek urls.py dosyasını da şu şekilde değiştirelim:

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

from django.conf.urls.defaults import *

# views.py dosyasında yazdığımız fonksiyonu burada çağırıyoruz.
# ama hangi sayfaya..
from mysite.views import current_datetime

# işte hangi sayfaya olduğunu buradan belirliyoruz.
urlpatterns = patterns('',
(r'^time/$', current_datetime),
)


Bu iki kod hakkında şimdilik sadece http://localhost:8000/time sayfasına, zaman ile ilgili bilgilerimizi yazdırdığımızı söyleyeyim. Dikkat edin, eğer Python dosyalarınızda Türkçe karakter kullanırsanız, kodun başına şunu eklemeyi unutmayın:

# -*- coding: utf-8 -*-
[...]


Hadi, hazır python manage.py runserver komutu yürürlükteyken, bir de şu linke bakalım; http://127.0.0.1:8000/time:
ss
NOT: Saat yanlış mı gösteriyor? settings.py dosyasını açın. TIME_ZONE satırını kendinize göre ayarlayın. Türkiye için:

[...]

# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'Europe/Istanbul'

[...]


Bir dahaki yazımızda emeklemeye başlayacağız.. :)