30 Ekim 2008 Perşembe

Google App Engine uygulama geliştirme 2

Google App Engine ile uygulama geliştirmenin ikinci sayısında aslında sizlere apilerden bahsedecektim ama farklı konulardan bahsedeceğim. Bunlar;

1. Google App Engine Django Kurulumu
2. Google App Engine ve Django Form Yaratma
3. Formları İşleme Ziyaretçi Defteri Uygulaması

Hiç laf ebeliği yapmadan olaya giriyorum çünkü uzun bir yazı olacak.

1. Google App Engine Django Kurulumu:
Öncelikle şunu söylemeliyim, Appengine'nin kendi web çatısı var ancak, dökümasyonu djangonun çok iyi ve sadece dökümasyon ile sınırlayamam artılarını. Bir kaç sebebden olsa gerek ısrarla django ile çalışıyorum appenginede. Şimdi sıra sıra nasıl Google'ın beleş uygulama motorunda çalışacağını görelim.

a) django-admin.py startproject yetis şeklinde bir proje başlattık. Ayrıntılara takılmayın isimler saçma bende profesyonel kodcu değilim :D

b) main.py

c) settings.py

d) app.yaml

application: app_engine_domain_adi
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
script: main.py

app.yaml dosyası hakkında daha önce neyin ne olduğunu anlatmıştım ve linklerde vermiştim bu sebebden dolayı bir daha üzerinden geçmiyeceğim. Şimdi bir deneme yapın ekranda django falan diyecek :D google_appengine/dev_appserver.py dosyanin_bulundugu_yer

e) Artık bir uygulama başlata biliriz ortam uygun hale geldi :D
> cd yetis
> python manage.py startapp Blog
uygulamamızın adı Blog olsun...

Artık Django'yu Google App Engine'de kullanabilirsiniz.

2. Google App Engine ve Django Form Yaratma ve İşleme:
Bu konudan açarak bahsetmek istiyorum bu nedenle link vermiyeceğim. Django Form işleme,yaratma,düzenlemenin Appengine'ye uyarlamasıdır, yani bu uygulama Django içindir Appengine sadece çalıştırır :D

Karışıklığı önlemek için dosya yapısının tree'sini veriyorum.
|----- app.yaml
|----- index.yaml
|----- main.py
`----- yetis
------|----- Blog
------|----|----- bform.py
------|----|----- models.py
------|----|----- templates
------|--------------- ziyaretci.html
------|--------- views.py
------|----- manage.py
------|----- settings.py
------------ urls.py

Django ile proje başlattık ( yetis ) ve birde uygulama açtık ( Blog ) . Şimdi sıra ile gidelim
a) Model oluşturulacak
b) Model için Form oluşturulacak

a) Model Oluşturulacak:
Modelimizi bir ziyaretçi defteri oluşturma uygulamasına göre oluşturuyorum.

from google.appengine.ext import db
class Z_Defteri(db.Model):
ad = db.StringProperty(verbose_name="Ad",required=True)
soyad = db.StringProperty(verbose_name="Soyad",required=True)
not_ = db.TextProperty(verbose_name="Mesaj")
inci = db.IntegerProperty(default = 0)
tarih = db.DateTimeProperty(auto_now_add = 1)
yazan = db.UserProperty()

def __unicode__(self):
return "%s %s %s %s"%(self.not_,self.ad,self.soyad,self.inci)

Modeldeki alanların parantezleri içindeki değişkenlerden bahsedelim.
verbose_name = "Ad" ----> Tablom oluştuğunda alanın ismini "Ad" yaptım. Yani şurası; <input type="text" name="ad" id="id_ad"
Peki neden bunu yaptık. Tabloya müdahale gücümüzü arttırmak için. Biz isim vermezsek kendisi uygun bir isim atıyacaktı zaten. Bunu neden biz yapmayalım :D
required = True ----> Bu özellik bizi zahmetten kurtarıyor. Şimdi bu alan gerekli mi_? gereksiz mi_? bir diğer değişle, bu alan hiç girilmesede olur mu? Bunu belirlemek için şöye dedik : luzumlu = Evet işte bunu söylüyoruz. Peki neden! Hata takibi yapmak için, eğer kullanıcı benım oluşturduğum bir tablonun alanını es geçerse ben ona hopbala, burayı doldurmadan geçiş izni yok diyorum :)
default = 0 ---> Ön tanımlı olarak sıfır değerini alsın.
auto_now_add = 1 ---> Tarihi commit yaptığımda otomatik oluştur.


b) Model için Form oluşturulacak:
Nedir! Ne değildir! Model için Form derken Modelin alanları için işlem yapabileceğim bir form alanı oluşturmakdan bahsediyoruz. Bunu el ile de yapabilirsiniz ama neden yapasınız! Bir sürü koddan ve hata takibinden kurtuluyorsunuz. Başlayalım! Öncelikle bform.py adında bir dosya oluşturalım. Dosyanın nerede oluştuğunu yukardaki tree'e bakarak görebilirsiniz.
bform.py

from models import Z_Defteri
from google.appengine.ext.db import djangoforms

class ZD_Form(djangoforms.ModelForm):
class Meta:
model = Z_Defteri
fields = ('ad','soyad','not_','tarih',)
exclude = ['inci','yazan']

----> "from models import Z_Defteri" ile modelimizin aldık
----> "from google.appengine.ext.db import djangoforms" Appengine'nin django'da bulunan ModelForm olayını kullanmamızı sağlayan modulunu aldık.
----> ZD_Form sınıfımıza djangoforms.ModelForm miras atadık. Buradaki ModelForm django'da 1.0 da var. Önceki versiyonunda yok 0,96 da NewForm olsa gerek :D
Öntanımlı değişkenlerden bahsedeyim.
-----> model = Z_Defteri burada modelimizdeki değişkenleri atadık
-----> fields = ('ad','soyad','not_','tarih',) kullanacağımız alanlar
-----> exclude = ['inci','yazan'] ilk form oluştuğunda form'da gözükmesini istemediğimiz alanlar.

bform.py dosyasının içine bu uygulamada kullanacağınız butun formları atabilirsiniz. Böylelikle herşey toparlı olmuş olur.
3. Formları İşleme Ziyaretçi Defteri Uygulaması
İstediğimiz model için istediğimiz formu oluşturduk. Şimdi bu oluşturduğumuz formu ekranda göstermek ve kayıt, düzenleme, silme gibi uygulamaları yapmak kaldı. Burada sadece kayıt olayını ele alacağım. Ziyaretçi defteri uygulaması örneği üzerinde form işlemeyi göreceksiniz!

Bunun için üzerinde değişiklik yapacağım dosyalar. template klasöründeki ziyaretci.html dosyası, Blog uygulamasındaki views.py ve yetis projesindeki urls.py dosyalarıdır. Yukardaki tree'ye göre dosyaların yerlerini tesbit edebilirsiniz.
Öncelikle views.py dosyası:

from django.http import HttpResponse, HttpResponseRedirect
from yetis.Blog.models import Z_Defteri
from bform import ZD_Form
from django.shortcuts import render_to_response
from google.appengine.ext import db
from google.appengine.api import users

Formları oluşturduğumuz yer bform.py den ZD_Form'u çektik, users,db apilerini ekledik, djangonun bir kaç fonksiyonunu ekledik.

def ziyaretci_defteri(request):
yazilanlar = Z_Defteri.all()
yazilanlar.order("-tarih")
yazilanlar = yazilanlar.fetch(10)

kullanici = users.get_current_user()
ndform=''
if kullanici:
k_islem = ("Hosgeldiniz, %s! (<a href=\"%s\">Cikis Yap</a>)" %(kullanici.nickname(), users.create_logout_url("/")))

if request.method == "POST":
zdform = ZD_Form(request.POST)
if ndform.is_valid():
yazan = kullanici
inc =Z_Defteri.all()
inci = inc.count()
not_ = (request.POST["not_"]).decode("utf8")
ad = (request.POST["ad"]).decode("utf8")
soyad = (request.POST["soyad"]).decode("utf8")
kayit = Z_Defteri(not_=not_,ad=ad,soyad=soyad,inci=inci,yazan=yazan)
kayit.put()
return HttpResponseRedirect('/')
else:
zdform = ZD_Form()

else:
k_islem = ("<a href=\"%s\">Giris Yapiniz</a>." % users.create_login_url("/"))

return render_to_response('ziyaretci.html',{'zdform':zdform,'yazilanlar':yazilanlar,'k_islem':k_islem,'kullanici':kullanici} )

Algoritması!
--->Önce sayfaya giren kişinin google kullanıcısı olup olmadığına bakıyoruz,
-------> google kullanıcısı ise ziyaretçi defterine not bırakmasına izin veriyoruz
-------------> Eğer Post ediliyor ve mothodumuz POST ise Form oluştur
-------------------->submit tuşuna basılmış ve Form boş bırakılmamışsa
-------------------------->Veritabanına Formda girilen alanları yaz.
-------------> Post edilmemiş ise sadece Form oluştur
--->değil ise google giriş sayfasına yönlendiriyoruz giriş yapıp tekrar yönlendirilsin.
Değişkenleri anlatacağım;
yazilanlar --> Ziyaretçi defterine yazılan yazının argümanlarının tamamını sorgu ile çekiyor.
kullanici --> Sayfayı ziyaret eden kişi. Dilerse deftere birşeyler yazabilir.
k_islem --> kullanici işemleri. Giriş ve Çıkış işlemi sadece :D
zdform --> Ziyaretçi Defteri form bilgilerini bu değişken ile alıyoruz. Form bu değişkende oluşuyor.

Burada daha fazla derine inmiyeceğim. Django'dan anlıyan arkadaşlar anlamışlardır diye umut ediyorum. Appengine kullanan arkadaşlar ise yeterince açıklayıcı olduğumu düşünüyorum.Sıra tempaltes kısmına geldi. Web sayfasında göstermek ve güzel görüntü oluşturmak için template kullanıyoruz.
Blog uygulaması içine bir templates klasörü açın ve içine ziyaretci.html dosyası açın. İçeriğinin bir kısmını bilgi amaçlı olarak burada, geri kalan tamamının linkini vereceğim.
en üstte {{k_islem}} koyarak kullanıcının gmail kullanıcı olup olmadığına bakarak yönlendirebiliriz.

<form action="." method="post">
<table>
{{zdform}}
</table>
<table>
<input type="submit" name="gonder" value="Gönder" class="inputsag"/>
</table>
</form>

Formumuz bu şekilde ekranda gözüktü :D zdform.as_b derseniz "b" halinde zdform.as_ul "ul" şeklinde zdform.as_table ise "table" şeklinde form oluşturur. Hiç birşey yapmazsanız sadece form oluşur.


{% for not in yazilanlar %}
<table>
<TD>
<p id="kisi">{{not.ad}} {{not.soyad}} <hr>
<em> id="eposta">{{not.yazan.email}}</em>
<em id="tarih">{{not.tarih|date:"d M Y D"}}</em></p>
<p> id="mesaj">{{not.not_}}</p>
</table>
</TD>
{% endfor %}

burada appengine ait olan yer "not.yazan.email" kısmıdır. Kullanıcının email adresini yazdırıyorum."not.tarih|date:"d M Y D"" burada ise tarihi filitre ederek ekrana basıyorum.
html dosyasının kod kısmı buradan ibarettir.

Çalışır halini görmek için

http://pythonizm.appspot.com



referanslar:
1- http://code.google.com/appengine/docs/datastore/creatinggettinganddeletingdata.html
2- http://appengineguy.com/2008/06/proper-unit-testing-of-app-enginedjango.html
3- http://www.djangobook.com/en/1.0/chapter07/
4- http://docs.djangoproject.com/en/dev/ref/forms/fields/
5- http://code.google.com/appengine/articles/django.html

21 Ekim 2008 Salı

Djangoya nasıl başlanmalı nasıl ilerlemeli ?

Bu konuda herkesin farklı görüşleri olabilir fakat benim edindiğim tecrübeler yardımıyla yeni başlamak isteyenler ve başlamış olup da nasıl devam etmesi gerektiği konusunda düşünceleri olan arkadaşlar aşağıdaki yollardan faydalanarak daha verimli gelişim gösterebilirler.

1) Buradan başlayın. Bir çok yerde djangobook ile başlamanız tavsiye edilir ama şu anki haliyle djangobook çok eksik kalmaktadır. Özellikle django 1.0'ın çıkmasıyla örneklerin bir çoğunu çalıştırmak için 1001 türlü takla atmanız gerekebilir.

2) 4 bölümden oluşan django tutorial'ı iyice anladığınıza inanıyorsanız. Django dökümantasyonuna geçebilirsiniz. Üstünde uzmanlaşmak istediğiniz alana göre buradan faydalanabilirsiniz.

3) How-to lardan inceleyebilirsiniz.

4) Dökümantasyonda ve how-to da anlatılanları aştınız ve ayrıntılara girmek istiyorsanız. Fonksiyonlar, sınıflar ve django ile ilgili her türlü ayrıntı için burayı ziyaret edebilirsiniz.

5) Yeni sürümlerle gelen özellikleri ve değişiklikleri takip etmek için burayı Herşeyi aştım birazda katkıda bulanayım diyorsanız da burayı ziyaret edebilirsiniz.

Sizin de eklemek istedikleriniz olursa tecrübelerinizi ve önerilerinizi yorumlar kısmında paylaşmanızdan memnuniyet duyacağız ;)

Bunlar yanında bizi izlemeye devam edebilirsiniz :)

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/

14 Ekim 2008 Salı

Django model veri tipleri

Bir veri tipi belirlerken dikkat etmeniz gereken 2 şey vardır:
  1. Field ismini rezerve edilmiş python kelimesi olamaz.
  2. Field ismi birden fazla alt çizgi ("_") işareti barındıramaz.
Field sınıfları 3 şeyi ifade etmek için kullanılır.
  • Database sütün tipi (örn: INTEGER, VARCHAR, INT...)
  • Django yönetici panelinin kullandığı her hangi bir widget (örn: )
  • Django yönetici panelinin minimal doğruluk gereklilikleri.
Şimdi bu alan tiplerine değinelim.

AutoField


Sayısal bir alan olup veri tabanındaki kayıtların artmasıyla otomatik olarak arttırılır. Büyük ihtimalle doğrudan kullanmanız gerekmeyecek; aksini belirtmediğiniz taktirde modelinize bir "primary key field" zaten ekleniyor. (:S Bu kısmı benden daha iyi anlayan biri varsa lütfen yorum olarak eklesin bilgilerini)

BooleanField


Doğru/Yanlış (True/False) bilgisi tutar.

CharField


Karakter katarı tutar çok uzun bir metin tutulacaksa bunun yerine TextField kullanılmalıdır.

Charfield fazladan bir parametreye ihtiyaç duyar : maxlength, bu alanınızın en fazla kaç karakterlik veriyi tutabileceğini ifade eder.

CommaSeparatedIntegerField


Virgülle ayrılmış sayıların tutulduğu bir alandır. Charfield gibi maxlength argümanına ihtiyaç duyar.

DateField


Tarih tutmak için kullanılan bir alandır. İki adet seçimlik argümanı vardır. Bunlar :
auto_now
Otomatik olarak kayıt edilme tarihini tutar. save() komutunu verdiğinizde tarih ne ise alanınız o tarih ile otomatik olarak kaydedilecektir.

auto_now_add
Otomatik olarak nesnenin ilk yaratıldığı tarihi tutar.


DateTimeField:


Tarih ve saat bilgisini tutar. DateField la aynı seçimlik argümanları kullanır.

EmailField


Email adresi tutmak için kullanılır. Email adresinin doğru olup olmadığı otomatik olarak kontrol edilir. maxlength argümanını kabul etmez en fazla uzunluk 75 karakter olarak sabitlenmiştir.

FileField


Bir dosya upload alanıdır. Sadece bir gerekli argümana sahiptir.
upload_to:
Yerel dosya sistemi yolu olup config dosyanızdaki MEDIA_ROOT yolu ile birleştirilip kullanılacaktır.


Bu yol strftime içerebilir. Örneğin MEDIA_ROOT dizininz /home/media olarak ayarlanmış olsun. upload_to parametresini "photos/%Y/%m/%d" olarak verirseniz. Django buradaki zaman damgalarını upload edilme tarihinden bakarak doldurur. (Örneğin %Y yıl'ın 4 basamaklı hali ile değiştirilir)

FileField ve ImageField alanlarını kullanmak için


  1. Ayarlar dosyanızda MEDOA_ROOT dizini Django'nun upload edilen dosyaları nereye koyacağını belirler. Buraya tam yolu yazın.
  2. Modelinize FileField veya ImageField ekleyin, upload_to argümanının dosyaların MEDIA_ROOT altında hangi alt dizine gideceğini belirlediğini unutmayın.
  3. Dosyanız kayıt edilden sonra Django size get__url fonksiyon sunar. Örneğin ImageField kayıdınızın adı profile_picture ise template dosyanızda {{ object.get_profile_picture_url }} şeklinde url'li kullanabilirsiniz.


Eğer dosyanın disk üzerindeki yerini, dosya boyutunu vs. öğrenmek isterseniz get_FIELD_filename(), get_FIELD_size() gibi fonksiyonları kullanabilirsiniz ayrıntılı bilgi için Djangobook'un Appendix C bölümüne bakın.

FilePathField


Seçimleri dosya sistemiz üzerindeki dosyalarla sınırlı olan bir alandır. Üç özel argümana sahiptir.
path
Gerekli, sistemdeki her hangi bir klasörü gösteren tam yol.

match
Seçimlik, bahsi geçen klasör içerisinde hangi dosyaları seçeceğini gösteren düzenli ifade.

recursive:

Seçimlik, True ise match ifadesi alt dizinlerde de aranır. False olarak öntanımlanmıştır.


Örnek: FilePathField(path="/home/texts", match="*.txt", recursive=True)

FloatField


Kayar noktalı sayı başka bir değişle ondalıklı sayı tutmak için kullanılır. Python'daki karşılığı float veri tipidir. İki adet argüman kullanır.
max_digits
Sayının en fazla sahip olabileceği basamak sayısı.

decimal_places
Sayının ondalıklı kısmının kaç basamaklı olacağını belirler.


ImageField


FileField ile aynıdır fakat upload edilen nesnenin doğru bir imaj olup olmadığını kontrol eder. Bunun yanında height_field ve width_field adında iki fazladan argümana sahiptir. Bu argümanlar imaj kaydedilirken otomatik olarak üretilip kaydedilirler. Bunun yanında FileField metodları (get_FIELD_*) burada da geçerli olup bunlara ek olarak get_FIELD_width() ve get_FIELD_height() metodları da ek olarak bulunmaktadır.

IntegerField


Tamsayı tutar.

IpAdressField


Bir ip adresini karakter katarı olarak tutar (örn: "127.0.0.1")

NullBooleanField


BooleanField gibir fakat bunun yanına bir adet de None değeri eklenmiştir. True/False/None değerlerini tutabilir.

PhoneNumberField


Özelleştirilmiş bir CharField tipidir fakat ek olarak girilen metnin U.S. tipi telefon numarası biçimlemesine uyup uymadığına bakar (XXX-XXX-XXXX)

Not: Başka bir ülkenin telefon numarasını kontrol etmek isterseniz django.contrib.localflavor pakedine bir göz atın.

PositiveIntegerField


IntegerField ile aynıdır fakat sadece pozitif tamsayıları tutar.

PositiveSmallIntegerField


PositiveIntegerField gibidir fakat belirli bir sayıya kadar izin verir. Maksimum değer kullandığınız veri tabanın SMALLINT veri tipinin pozitif olarak ulaşabildiği kullanabildiği maksimum (Genellikle 65535) değerdir.

SlugField


Slug ingilizce bir gazetecilik terimidir. Her hangi bir şey için kısa bir etiket olabilir. Sadece harf,sayı ve alt çizgi karakteri içerebilir. Genelde URLler tarafından kullanılır. Örneğin bir bloglarda görmüşsünüzdür "Hırsızlar Nerede?" başlığı ile kaydettiğiniz yazı url'de "hirsizlar-nerede" şeklinde gözükür. İşte başlığın çeşidine slug diyoruz. (bu kısım hakkında benden daha fazla bilgisi olan lütfen yorum olarak eklesin.)

CharField da olduğu gibi maxlength parametresi alabilir eğer almadıysa öntanımlı maxlenth parametresi 50 karakterdir.

Slugfield prepopulate_from adında fazladan bir seçeneğe sahiptir. Bu slug metninin, nesnenizin django admin panelindeki hangi alan(lar)ının birleşiminden otomatik olarak oluşturulacağını belirler. kullanımı models.SlugField(prepopulate_fpom=("pre_name", "name")) gibidir.

SmallIntegerField


PositiveSmallIntegerField'ın aynısıdır fakat buradaki sayı işaretlidir. Genellikle -32,768 ile +32,767 arasındaki sayıları ifade edebilir.

TextField


Sınırsız metin alanıdır.

TimeField


Günün saatini barındırabilen bir alandır. DateField ve DateTimeField'ın sahip olduğu otomatik oluşturma seçeneklerini bu da barındırır.

UrlField


Bir url tutmak için kullanılır. Eğer verify_exists argümanı True olarak geçirilirse adresin doğruluğu kontrol edilir (kontrol adrese ping atmak vasıtası ile gerçekleştirilir).

XmlField


TextField ile aynıdır fakat xml tutmak için kullanılır. Xml söz dizimini kontrol eder. Söz diziminin doğruluğunu kontrol etmek için RELAX NG şemasının yerini dosya yolu olarak vermeniz gerekmektedir.

11 Ekim 2008 Cumartesi

Google App Engine uygulama geliştirme 1

Son zamanlarda web programlama öğrenme azmimin sonunda galib geleceğimi ve bana çok uzak olan bu alanda kendime birşeyler katabileceğimi gösteriyor. Web programlama diyince akla gelen çatılara değiştirerek bir yenisini ekleyen ve iyiki olan Google'in APP ENGINE uygulaması ile web uygulamaları geliştirmeye bende başladım. Biraz araştırma, biraz deneme yanılma yöntemiyle mantığını azda olsa kavramış bulunmaktayım. App Engine yeni! djangoyu kullan, dökümasyonda sıkıntı çekersin veya sırf beleş hosting var o yüzden kullanıyorsun! diyenleri duyar gibiyim. Ne yalan söyleyim haklısınız ama önce aşağıdakileri okuyun.

  • 500 mb web alanı,

  • 9 tane app engine uygulaması açabilirsiniz ki bu toplamda 4500 mb'lık web alanı demek,

  • Aylık 5 milyon sayfa gösterimi için her App Engine uygulaması 500 mb'a kadar depo, yeterli band genişliği ve cpu kullanamı sağlıyor.

  • Uygulama version takip sistemi. Bunu alatmak zevkli olacak çünkü herkezin hoşuna gideceğine inanıyorum. Buraya bir yıldız atalım ve aşağıda anlatalım. *Version Takip

  • Google App Engine admin panelini unutmamış, istatistiklerin tutulduğu, version seçiminin yapılabildiği ve dilerseniz uygulamanıza varsa Domain adresinizle bütünleştirebilirsiniz. Bunlarla artı olarak milyonlarca tabloyu yönetmek için veri gösterim bölümü var(data viewer)... Uygulamanızın çalışma esnasındaki Log'larınızı takip edebilir ve hataları görebilirsiniz.

  • App Engine'nin bir özelliği daha çok hoşuma gidiyor. Henüz kullanmak nasip olmadı ama:D Admin panelini incelerseniz orada Developers yazan bir kısım var. Geliştiriciler bölümünde projenize istediğiniz kadar kullanıcıyı dahil edebilir ve ortak bir çatı altında uygulamalarınızı yönetebilirsiniz. Tek yapmanız gereken geliştirici olacak kişinin gmail adresini buraya yazmak.

  • Modeller,Template,Static dosyaları, kendi web uygulamaları için frameworkü ve en güzeli baştan aşağıya python ile web uygulamaları geliştirebileceğiniz açık kaynak kodlu güzel bir çalışma ortamı ve sağlayıcısı.


*Version Takip Açıklaması : Benim çok hoşuma giden ve sizinde çok hoşunuza gideceğine inandığım bir uygulamadan bahsedeceğim. Appengine'de ayar dosyasında şöyle birşey vardır.

application: gencistatistik
version: 2
runtime: python
api_version: 1


  • application kısmı uygulamamızın AppEngine'deki adını yazılıyor

  • runtime kısmı uygulamanın hangi dili kullandığını

  • api_version api versionudur. Bu kısmı pek anlamış değilim

  • version bu kısımda projenizi versionlara ayırabilirsiniz.

  • Örneğin bir blog uygulaması yapıyorsunuz. Geliştirdiğiniz blog uygulamanızı makinanızda google_appengine/dev_appserver.py sitem/ şeklinde test ettiniz hiç bir sorun yok, o zaman dediniz ki ben bunu geliştireceğim ve bunun üzerine gelişmiş versionlar koyacağım. Appengine size bu fırsatı tanıyor ve version kısmına 1 yazarsanız her alanınıza yüklediğinizde(google_appengine/appcfg.py update sitem/) 1 ve üstü versionlar olur. Diyelimki artık blog uygulamanız yeterince gelişti ve siz hataları görmek için 1 sürümünü kaldırmadan version kımına 2 yazdınız ve alanınıza yüklediniz. App Engine'de artık hem 1. ve hem 2. sürümler mevcut. Admin panelinden hangisini öntanımlı(default) version olarak seçerseniz o sürüm uygulama.appengine.com adresinde gözükür. Diğeri ise geliştiriciler tarafından test etmek amacı ile kullanılabilir. Süper değil mi? :D


    İştahınızın kabardığını düşünüyorum ve birazda icraat dediğinizi duyuyorum. Açıkcası bu yazıyı yazmadan 1 gün önce appengine ile merhabalaştım :D bir gün sonra küçük bir blog uygulaması yaptım.( http://gencistatistik.appspot.com/ ) Nereden başlıyacağınızı bilmiyorsanız pytr.org adresinde güzel referans olarak kabul ediyorum. Çok güzel bir anlatım tarzıyla konuyu özetlemişler, nasıl hesap alacağınızı, nereden başlıyacağınızı, kavramları ve başlangıç teknikleri. ( TIKLA )

    Django kullanan arkadaşlarımın çabuk adapte olacağına inanıyorum. Ben uygulamamda django kullanarak değil App Engine'nin kendi Framework'ünü kullanıyorum. Kendi blog adresimden bir örnek ile bitirmek hayırlı olacak uzadıkça uzuyor :D Öncelikle pytr.org adresindeki makaleleri okuduğunuzu varsayıyorum.
    Dosyanın içerik listesi.
    mysite
    ------>static
    ------>python
    -------------->templates
    ---------------------------->blogyaz.html
    ---------------------------->index.html
    -------------->hello.py
    ------>app.yaml
    Python dosyası sadece bir tane var. Bütün python kodları aynı yerde, parçalamadım.

    from google.appengine.ext import webapp
    from google.appengine.ext.webapp.util import run_wsgi_app
    from google.appengine.api import users
    from google.appengine.ext import db
    from google.appengine.ext.webapp import template
    #Blog uygulamamda kullanmak için tablolarım.
    class Blogum(db.Model):
    yazan = db.UserProperty()
    girdi = db.TextProperty()
    blogbaslik = db.StringProperty()
    date = db.DateTimeProperty(auto_now_add=True)

    class Karsilama(db.Model):
    yazan = db.UserProperty()
    yazi = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)

    Kısaca Blogum ve Karsilama tabloları oluşturdum. Appenginede djangoda olduğu gibi modeli oluşturmama gerek yok. İsterseniz çalışma anında dahi tablolara müdahale edebilirsiniz :D Karsilama gelen kişiye mesaj yazma veya algılama için oluşturdum. Tablolar çok basit olabilir ama buda bir örnek :D

    class AnaSayfa(webapp.RequestHandler):
    def get(self):
    bloglar = Blogum.all()
    bloglar.order("-date")
    kullanici = users.get_current_user()
    if kullanici:
    url = users.create_logout_url(self.request.uri)
    url_linktext = "Çıkış"
    else:
    url = users.create_login_url(self.request.uri)
    url_linktext = "Giriş"
    template_values = {
    "bloglar":bloglar,
    "url":url,
    "url_linktext":url_linktext,
    "kullanici":kullanici}
    path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
    self.response.out.write(template.render(path, template_values))

    Class'larımız eğer biz appenginenin kendi web çatısını kullancaksak miras alıyoruz. Burada miras olarak webapp sınıfının fonksiyonu RequestHandler'i aldık. get fonksiyonunda yolluyor post fonksiyonu ile gelen veriyi yorumluyoruz. bloglar = Blogum.all() ile blogum tablosuna sorgu çekiyor ve order("-date") ile güncel tarihe göre sıralatıyoruz. (SQL nerde :D) Modeller ve alanları ile ilgili daha geniş bilgi için TIKLA burayı biraz kurcalayın.
    kullanici = users.get_current_user() burada Appenginenin Users Api'sini kullandık ve get_current_user() ile en basit söylem ile giren üye mi? öğrendik :D Üye ise çıkış yapmasını , üye değil ise google'ın giriş sayfasına yönlendirdik.

    Path dosyasında index.html dosyasının yerini aldık ve self.response.out.write(template.render(path, template_values)) ile template sözlüğündeki anahtarları index.html dosyamızda kullanmak üzere yolladık :D Artık html dosyamız ile işlemlerimize devam edebiliriz. Şimdilik bu kadar yeter sindirin ve kurcalayın html dosyalarımızda yolladığımız bu anahtarları nasıl kullandığımızı, static dosya mantığı, app.yaml dosyasının mantığı, admin paneli ve inşallah Appengine'deki uygulamamın içinde google api'lerinin nasıl kullanıldığını anlatacağım. Eksiğim yanlışım veya düzeltilmesi gereken bir yer, konu veya mantık hatası varsa lütfen uyarınız.

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

Mechanize Modülü ve Vodafon Örneği

Bildiğiniz gibi Vodafone kullancılarının günlük sadece bir mesaj hakkı vardır. Ancak bu mesaj hakkını 1 tane olmasından ve uğraşmak istemediğimizden kullanmayız. Bu python betiği ise üşengeç olup bir tanede olsa kullanırım diyenler için işe yarayabilir ama daha çok Python'dan anlayan insanların "Mechanize" modülüne örnek olması amaçlanmıştır.

Mechanize modülü kurulumu:
- Pardus'da konsoldan "sudo pisi it mechanize".
- Windows'da setup. direk kuruluma sahibtir.

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import mechanize
#modülümüz yüklendi
def baglan():
global b
b=mechanize.Browser()
b.open('https://www.vodafone.com.tr/MyVodafone/login.php')
b.select_form(nr=1)


mechanize.Browser() ile tarayıcımızı oluşturduk, open ile sayfayı açtık, select_form ile sayfadaki 1. formu seçtik. Peki nedir bu form? Bu form bizim vodafona giriş için kullanacağımız kullanıcı adı ve şifresi bölümüdür. Daha açık bir şekilde bu form aşağıdaki gibidir;

>>> b.select_form(nr=1)
>>> print b
<browser visiting="" tr="" myvodafone="" php="" selected="">
<post tr="" myvodafone="" php="" application="" urlencoded="">
<textcontrol(gsmno=)>
<passwordcontrol(mypass=)>
</passwordcontrol(mypass=)></textcontrol(gsmno=)></post></browser>


Görüldüğü üzere sayfanın yukardan aşağıya doğru sıralamasında 1. form statüsünde olan formu seçtik çünkü vodafona giriş yapmak üzereyiz. Bu formda iki alan gözüküyor, bunlardan birincisi GsmNo diğeri MyPass. Sorumuz ise bu form girişlerini nasıl yapacağımız olacak !
Devam edelim!

def giris():
global b
gsmno=raw_input("GSM NO :") # numara girişi(543)
vodos=raw_input("Vodafon Şifreniz:") #-->şifre
b["GsmNo"]=gsmno # form girişi yapılıyor
b["MyPass"]=vodos
print "Bağlaniyor"
r=b.submit() # form bilgileri yollanıyor

try:
b.open('https://www.vodafone.com.tr/MyVodafone/myvodafone.php?pageId=WebSms') # websms sayfası
b.select_form(nr=1) #--------------->websms sayfasındaki (mesaj yollama) formumuz
except:
print "Bağlandi"
print "Hatalı Numara veya Şifre"
exit(1)

Buraya kadar yaptıklarımızı özetleyelim.
1. Vodafon sayfasını açıldı,
2. Vodafon sayfasına giriş yapıldı,
3. Girişimiz hatalı değil ise mesaj yollama sayfası açıldı,
Geriye sadece mesaj yollamak kaldı.
def mesaj_cek():
global b
try:
print "Mesaj Yollanacak Numaranın(Örn 543) kodu:"
yolk1=raw_input()
print "Mesaj Yollanacak Numara(Örn 4658758) kodu:"
yolk2=raw_input() #Örnein 4658758
try:
b["WebSimSmsUserGsmPrefix"]=[yolk1] #---->Numaramızın ilk 3 hanesi
b["WebSimSmsUserGsmNo"]=yolk2 #-------->Numaramızın devamı
except:
print "yanlis giris yaptiniz!"
exit(1)
print "Yollacak Mesajı Giriniz:"
mesaj=raw_input() #------------------------->Yollanacak mesaj
b["WebSimSmsText"]=mesaj #------------------>Mesajımız forma girildi
print "Mesaj yollanıyor"
r=b.submit() #------------------------------>Mesaj yollandı
print "Mesaj yollandı"
except:
print "GUNLUK SADECE 1 MESAJ HAKKINIZ VAR!!!"
exit(1)
b.close()
baglan()
giris()
mesaj_cek()


Bu kodun tamamı Burada
Neler yapılabilir;
  • Sınırsız mesaj sayfasından,sınırsız mesaj çekilebilir
  • Diğer operatörlerden benzer uygulamalar yapılabilir
  • Bayram,kandil,yıl başı gibi toplu mesaj atılmak istendiğinde bir veritabanı oluşturup,veritabanındaki listedeki kullanıcılara mesaj atılabilir
  • İstediğimiz web sayfasından istediğimiz bilgiyi alabilir ve web sayfalarını otomatikleştirebiliriz

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.