tag:blogger.com,1999:blog-72471553065071711012023-06-15T10:22:45.546-07:00Python DeneyimlerimizJabber'da, Irc'de anlatacağıma, buraya yazarım; kafadan silinir, buradan silinmez!Unknownnoreply@blogger.comBlogger63125tag:blogger.com,1999:blog-7247155306507171101.post-49695368395402657362011-06-18T02:28:00.000-07:002011-06-18T02:28:16.435-07:00Python Geliştirme Ortamları--- Bu yazı yeni başlamayı düşünenler içindir ---<br />
<br />
<blockquote>Python'a yeni başlıyorum ve windows ortamında geliştirmek istiyorum bana development ortamı için yapmam gerekenleri ve yararlı toollar önerebilir misiniz? </blockquote><br />
<h2>Windows'ta Geliştirme Yapmak</h2><br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="http://www.resimsehri.com/wp-content/uploads/2011/04/Ac%C4%B1-Resimleri4.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://www.resimsehri.com/wp-content/uploads/2011/04/Ac%C4%B1-Resimleri4.jpg" width="301" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Windows Dert Ortamı</td></tr>
</tbody></table><br />
Açıkcası bu soruyu cevaplarken biraz kurgu yaparak konuşacağım zira Windows ortamında pek geliştirme yapmadım. Yaptığım sırada ise yaptığım sadece daha önce geliştirdiğim bir aleti Windows'a port etmeye çalışmaktan ibaretti. Python'un kurulması, bağımlılıkların yerleştirilmesi ve geliştirmeye başlamadan önce gerekli ayarların yapılması hepsi benim için birer çileye dönüştü. Daha sonrasında ise <a href="http://tr.wikipedia.org/wiki/DOS">Dos</a> komut isteminde çalışmak, gerektiğinde <a href="http://tr.wikipedia.org/wiki/SSH">ssh</a> ile uzak makineye bağlanmak çilenin noktası oldu benim için. Bilmiyorum belki Linux ortamlarına alıştığım içindir ama gerçekten zordu. / Bu konuda yorumlarınızı bekliyorum.<br />
<br />
<b>Eğer Bugün Windows Üzerinde Geliştirme Yapacak Olsam;</b><br />
<br />
Bağımlılık kurma meselesini <a href="http://www.pip-installer.org/en/latest/index.html">pip</a> Kullanarak çözmeye çalışırdım. Bir kere kurduktan sonra kendisi Python paketleri için kolay bir bağımlılık kurma aracı olarak çalışıyor. Terminalde ya da Dos ortamında,<br />
<br />
<code class="bash">pip install hede</code><br />
<br />
Diyerek hede pakedinin kurulmasını sağlayabiliyorsunuz. Ancak bazı modüller pip ile uyumsuzlar. Örneğin geçen gün imaj görüntüleme ve düzenleme pakedi olan <a href="http://www.pythonware.com/products/pil/">PIL</a>'i kurmaya çalıştığım zaman çalışmadığını gördüm. Baya bir uğraştan sonra pip kullanırken PIL pakedini direkt olarak kurmamamız gerektiğini, onun yerine <a href="http://pypi.python.org/pypi/Pillow/1.0">Pillow</a> adlı PIL pakedinin uysallaştırılmış bir versiyonunu kurmak gerektiğini öğrendim.<br />
<br />
Bunun dışında bazı paketleri yüklerken başka dillerden kütüphaneler derlenip kurulmaya çalışılıyor bu yüzden sistemde <a href="http://gcc.gnu.org/">GCC</a>'nin kurulu olması gerekli.<br />
<br />
Neyse sözü uzatmayayım, <br />
<br />
<h2>Siz En iyisi Linux Kullanın</h2><br />
Her zaman söylenir, developer olmaya niyetlenmiş kişinin linux kullanması daha iyidir diye. Sebebi basit, ihtiyacınız olan olabilecek bütün tool'lar kütüphaneler sisteme kurulu olarak gelir. Olmayanları da paket yöneticiniz ile kurar geçersiniz. Dos ekranında komut vermektense bir Linux terminalinde komut vermek her zaman daha kolay ve sağlıklıdır.<br />
<br />
Linux ortamında geliştirmeye başlamak için size gerekli olan tek şey kendinize bir ide ya da editor seçip çalışmaya başlamanızdır. Linux camiasının iki kallavi editörü var, bunlardan biri <a href="http://www.eksisozluk.com/show.asp?t=emacs">emacs</a>, diğeri ise <a href="http://www.eksisozluk.com/show.asp?t=vim">vim</a>. İkisi de çok güçlü araçlar. İkisi için de eklenti geliştiren binlerce insan vardır sanırım. Ancak söz konusu dil Python ise ben <a href="http://www.eksisozluk.com/show.asp?t=pycharm">PyCharm</a>'ı tek geçerim. İndirip kullanın, hiç bir kısıtlama yok. Sadece deneme süresi geçtikten sonra kendisini yarım saatte bir kapatıyor. Bence iyi bile sayılabilir böyle olması zira ben bazen bilgisayarın başından kalkmayı unutuyorum.<br />
<br />
Sanırım soruya cevap vermiş oldum. Bir daha ki yazıda görüşmek üzere esenkalın.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com2tag:blogger.com,1999:blog-7247155306507171101.post-87592926360148766062009-11-05T14:25:00.001-08:002009-11-05T15:30:36.244-08:00Appengine'de Mail Api'nin KullanılışıWeb sayfanızda iletişim bölümünde hazırladığınız bir form olsun ve sonuçlarını mail adresine gelmesini istiyorsunuz o zaman bu yazı size faydalı olabilir. Sıralama şu şekilde, 1.Formunuzu oluşturun, 2.Veritabanı için modelinizi yazın, 3.Formdan geleni işleyin. Öncelikle dosya yapımız;<br /><br />|----- app.yaml<br />|----- iletisim.py<br />|----- model.py<br />|----- templates<br />|----------iletisim.html<br /><br />Şeklindedir. Sıra sıra gitmek istiyorum. Html formumuzu oluşturalım(template/iletisim.html);<br /><br /><FORM action="/iletisim" method="post"><br /> <label for="id_ad"><br /> Ad:<br /> </label><br /> <input type="text" name="ad" id="id_ad" autocomplete="off"/>*<br /> <label for="id_soyad"><br /> Soyad:<br /> </label><br /> <input type="text" name="soyad" id="id_soyad" autocomplete="off"/>*<br /><input type="submit" value="Yolla" name="form_iletisim"><br /> </FORM><br /><br />İsim ve soyisim girişi yapıldığında ve "Yolla" tıklandığında bilgilerin mail adresinize gelmesi için bir kaç adım var. Öncelikle modelimizi oluşturan python kodumuzu yazalım ("model.py")<br /><br /><code class="python"><br />from google.appengine.ext import webapp,db<br /><br />class Basvuru_(db.Model):<br /> """<br /> Basvuru yapilacagi zaman kullanilacak olan model<br /> """<br /> ad = db.StringProperty(verbose_name="ad",required=True)<br /> soyad = db.StringProperty(verbose_name="soyad",required=True) <br /><br />##Otamatik Form Olusturmasi icin Kullanabilirsiniz<br />class Basvuru_form(djangoforms.ModelForm):<br /> #Kullanisi<br /> class Meta:<br /> model = Basvuru_<br /> fields = ('ad','soyad')<br /></code><br /><br />Modelimizi de olusturduktan sonra formdan gelen veriyi islemeye geldi. Bunun icin iletisim.py python dosyamızı oluşturup işlemlerimizi yapıyoruz.<br /><br /><code class="python"><br />from google.appengine.ext.webapp import template<br />from google.appengine.ext.webapp.util import run_wsgi_app<br />from google.appengine.api import users,mail<br />from django.shortcuts import render_to_response<br />import os,sys<br /><br />class Iletisim(webapp.RequestHandler):<br /> def get(self):<br /><br /> template_values={}<br /> path = os.path.join(os.path.dirname(__file__), 'templates/iletisim.html')<br /> self.response.out.write(template.render(path, template_values))<br /> <br /> def post(self):<br /> veri = Basvuru_form() #Bos girilip girilmedigini kontrol eder<br /> if not veri.is_valid():<br /> ad = up(unicode(self.request.POST["ad"]).encode("utf-8"))<br /> soyad = up(unicode(self.request.POST["soyad"]).encode("utf-8"))<br /> #TURKCE YAP<br /> if ad and soyad: # isim ve soyisim girilmemisse formu kaydetmez<br /> kayit = Basvuru_(ad=ad,soyad=soyad)<br /> kayit.put()<br /> <br /> if not mail.is_email_valid(ad): #eger isim yazmamissa size mail atmaz<br /> pass<br /> else:<br /> sender_address = "yetis.m@gmail.com"<br /> yollanan_adres="yetis.m@gmail.com,bilgi@spssanaliz.net"<br /> subject = "Birisi Formu Doldurdu"<br /> body ="\nAd Soyad : "+ad+" "+soyad+"formunuzu doldurdu."<br /> mail.send_mail(sender_address,yollanan_adres, subject, body)<br /> self.redirect("/ulasildi")#Burada form yollama basarili oldugunu gösteren bir mesaj verdirebilirsiniz.<br /> else:<br /> self.response.out.write("Bilgileri eksik girdiniz lütfen tekrar deneyiniz!!!<a href="'/iletisim'">iletisim</a>") <br /> else:<br /> self.redirect("/hata")<br />application = webapp.WSGIApplication(<br /> [<br /> ('/iletisim',Iletisim),<br /> ], debug=True)<br /></code><br /><br />Bunlara ek olarak dikkatinizi çekmiştir. "up" fonksiyonu kullanılmış, Türkçe karakter sorununu kaldırmak üzere bir arkadaşımdan bulduğum fonksiyonu kullanabilirsiniz. İşinizi oldukça göreceğini düşünüyorum ki sadece python'da değil, hangi dilde olursa olsun bu mantık ile Türkçe karakter problemlerini ortadan kaldırabilirsiniz. Eğer Türkçe karakter (ı,ğ,ü,ş,İ,ö,ç vb..)girilmiş ise büyük harfe çevip bu karakterlerden arındırıyor. Fonksiyonumuz;<br /><br /><code class="python"><br />def up(text):<br /> """Girilen TR karakterleri EN karakterlere cevirir"""<br /> groupone = ["a", "b", "c", "\xc3\xa7", "\xc3\x87", "d", "e", "f", "g", \<br /> "\xc4\x9f", "\xc4\x9e", "h", "\xc4\xb1", "i", "\xc4\xb0", \<br /> "j", "k", "l", "m", "n", "o", "\xc3\xb6", "\xc3\x96", "p", \<br /> "q", "r", "s", "\xc5\x9f", "\xc5\x9e", "t", "u", "\xc3\xbc", \<br /> "\xc3\x9c", "v", "w", "x", "y", "z",\<br /> "\xfe","\xde","\xfd","\xdd","\xf0","\xd0","\xfc","\xdc","\xf6","\xd6","\xe7","\xc7",\<br /> "\u015f"]<br /><br /> grouptwo = ["A", "B", "C", "C", "C", "D", "E", "F", "G", "G", "G", "H", \<br /> "I", "I", "I", "J", "K", "L", "M", "N", "O", "O", "O", "P", \<br /> "Q", "R", "S", "S", "S", "T", "U", "U", "U", "V", "W", "X", \<br /> "Y", "Z",\<br /> "S","S","I","I","G","G","U","U","O","O","C","C",\<br /> "S"]<br /> for counter in range(len(groupone)):<br /> text = text.replace(groupone[counter], grouptwo[counter])<br /> return text<br /></code><br /><br />Uzun zamandır blogumuzda yazı göremiyorum. Eskiden zevkle okuyordum. Bu yazı benim 20 dakikamı aldı. Özellikle uzak sunucu işlemleri için yazıları çok merak ediyorum ve jquery,ajax,python üclüsünü kullanacak örneklerde sizlerden beklemekteyim.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Yetişhttp://www.blogger.com/profile/03568362306405214586noreply@blogger.com1tag:blogger.com,1999:blog-7247155306507171101.post-75272304570481537252009-09-03T03:54:00.000-07:002009-09-03T04:31:59.691-07:00Django'da iki sunucuda birden çalışmak ve settings.pyŞu sıralar uğraştığım bir Django uygulaması var geliştirirken karşılaştığım bir sorunu ve çözümünü paylaşayım dedim.<br /><br />Geliştirdiğim uygulamayı sunucuya yükledikten sonra lokalde geliştirirken oluşturduğum bir çok seçeneğin sunucudayken değişmesi gerektiğini farkettim. Bu ayarları değiştirmek kolaydı fakat sıkıntı çektiğim nokta uygulamanın hem sunucuda hemde kendi laptopumda tek bir settings.py ile sorunsuzca çalışması gerekiyordu. Bende şöyle bir çözüm buldum :<br /><br />settings.py :<br /><code class = "python"><br />from os import uname, getcwd<br />from os.path import join<br />MACHINE_NAME = uname()[1]<br />if MACHINE_NAME == "web77.webfaction.com":<br /> DOCUMENT_ROOT = "/path/to/document/"<br /> DATABASE_ENGINE = ...<br /> DATABASE_NAME = ...<br /> DATABASE_USER = ...<br /> DATABASE_PASSWORD = ...<br /> DATABASE_HOST = ...<br /> DATABASE_PORT = ...<br />else:<br /> DOCUMENT_ROOT = getcwd()<br /> DATABASE_ENGINE = 'sqlite3'<br /> DATABASE_NAME = join(DOCUMENT_ROOT,'sqlite3.db')<br /> DATABASE_USER = ''<br /> DATABASE_PASSWORD = ''<br /> DATABASE_HOST = ''<br /> DATABASE_PORT = ''<br /></code><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-6476312228542434772009-08-07T12:12:00.000-07:002009-08-07T12:17:10.702-07:00Yeni bir tat...Python gezegenine bir <a href="http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.2">girdi</a> düştü... Richard Jones adlı arkadaş hafif ve basit bir gui sistemi üzerinde çalışıyormuş. Anlaşılan en güzel tarafı araç kitinin tam pythonic bir yazıma sahip olması <br /><br /><code>import withgui<br />gui = withgui.Window()<br />gui.image('http://www.python.org/images/python-logo.gif')<br />gui.run()</code><br /><br />sonuç : <br /><br /><img src= "http://www.mechanicalcat.net/images/image.png" alt= "output"><br /><br />Ne yalan söyleyeyim beni meraklandırmayı başardı :)<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com2tag:blogger.com,1999:blog-7247155306507171101.post-72973029742300433102009-06-16T12:46:00.000-07:002009-06-16T15:00:26.024-07:00PyS60 ile Dosya TarayıcısıMerhabalar,<br /><br />Birkaç gündür Symbian Python'u inceliyorum çok yakında bu konuda ayrıntılı dökümanlar yazacağım...<br />Bu yazıda Symbian telefonlar için çok çok basit bir dosya tarayıcısı yazacaz...<br /><br />Lafı fazla uzatmadan anlatmaya geçelim,<br /><br />Modülümüzü import ediyoruz ve uygulamanın başlığını ayarlıyoruz...<br /><code class=python><br />import os<br />from appuifw import *<br /><br />app.title = u"Dosya Tarayicisi"<br /></code><br /><br /><code class=python><br />while True:<br /> liste = [u"x Cikis", u"< Geri"]<br /> for i in os.listdir(os.getcwd()): liste.append(unicode(i))<br /></code><br />Bu kısımda dizin içeriğini alıyoruz ve tüm içeriği unicode şeklinde listeye ekliyoruz (telefonda utf-8 kullanılması gerektiği için)<br /><br />döngüye devam ediyoruz...<br /><code class=python><br /> i = selection_list(liste, 1)<br /> if liste[i] == u"x Cikis": break;<br /> elif liste[i] == u"< Geri":<br /> os.chdir("/".join(os.getcwd()[:-2].split("/")[:-1]) + "//")<br /> continue;<br /> else: os.chdir("%s%s" % (os.getcwd(), liste[i]))<br /></code><br />Bu kısımda <em>selection_list</em> ile dizini listeliyoruz bu fonksiyon seçilen elamanın listedeki indexini verir...<br />(örneğin; ilk eleman seçildiyse 0 döndürür)<br />ayrıca <em>selection_list</em> <em>raw_input</em> gibidir uygulamayı bekletir bir eleman seçildiğinde değerini döndürür ve kod aşağıya doğru devam eder...<br /><br />daha sonraki işlemler ise seçilen elemanlar neyse ona göre işlem yapılıyor, Geri işlemi ise bulunulan dizinin son kısmı silinerek yapılıyor...<br /><br />ve eğer "geri" veya "cikis" seçilmediyse <em>bulunulan_dizin + secilen_dizin </em>e giriliyor, ve tekrar listeleme yapılıyor bu şekilde döngü devam ediyor...<br /><br />Ve son olarak kodun tamamı,<br /><code class=python><br /># -*- coding: utf-8 -*-<br /># s60 dosya tarayıcısı denemesi<br /># coded by rohanrhu<br /><br />import os<br />from appuifw import *<br /><br />app.title = u"Dosya Tarayicisi"<br /><br />while True:<br /> liste = [u"x Cikis", u"< Geri"]<br /> for i in os.listdir(os.getcwd()): liste.append(unicode(i))<br /><br /> i = selection_list(liste, 1)<br /> if liste[i] == u"x Cikis": break;<br /> elif liste[i] == u"< Geri":<br /> os.chdir("/".join(os.getcwd()[:-2].split("/")[:-1]) + "//")<br /> continue;<br /> else: os.chdir("%s%s" % (os.getcwd(), liste[i]))<br /></code><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Oğuzhan Eroğluhttp://www.blogger.com/profile/09142565628105212005noreply@blogger.com5tag:blogger.com,1999:blog-7247155306507171101.post-58581330811505969102009-05-09T12:24:00.000-07:002009-05-09T12:28:00.745-07:00Google App Engine İçin Özel Şablon Yardımcıları<a href="http://code.google.com/appengine">GAE</a> ile bir uygulama geliştirirken şablon kısmında ekrana yazılan değeri biçimlendirmem gerekti. <a href="http://pythontr.blogspot.com/2008/10/django-ablonlar-iin-zel-etiketler.html">Bu konuyla alakalı daha önce Django için bir yazı yazmıştım</a>. Google App Engine de ise durum Django dan biraz farklıymış. Özel şablon yardımcıları oluşturmak için ilk olarak ana dizinde ya da herhangi bir dizinde bir dosya oluşturuyoruz. Örneğin ana dizinde customfilters.py adında bir dosya oluşturalım:<br /><br />Dosyaya öncelikle webapp modülünü dahil ediyoruz:<br /><code class="python"><br />#-*- coding: utf-8 -*-<br />from google.appengine.ext import webapp<br /></code><br /><br />Ardından fonksiyonlarımızı şablon içinde kullanabilmemizi sağlayan kaydediciyi oluşturuyoruz.<br /><code class="python"><br />register = webapp.template.create_template_register()<br /></code><br /><br />Sonrada fonksiyonumuzu yazıyoruz. Fonksiyon gelen bağlantıdaki boşlukları - karakteri ile değiştirip geriye sonucu döndürüyor.<br /><code class="python"><br />def escape_url(url):<br /> return url.replace(' ','-')<br /></code><br /><br />Son olarakta oluşturduğumuz fonksiyonu kaydediyoruz.<br /><code class="python"><br />register.filter(escape_url)<br /></code><br /><br />Şimdi customfilters.py dosyamızı projemize tanıtmamız gerekiyor. Bunun içinde main fonksiyonunun içine aşağıdaki kodları ekliyoruz:<br /><code class="python"><br />def main():<br /> webapp.template.register_template_library('customfilters')<br /> run_wsgi_app(application)<br /><br />if __name__ == "__main__":<br /> main()<br /></code><br /><br />Bu sayede customfilters.py dosyamızı projemize tanıtmış oluyoruz. Bu tanıtım işlemi ile birlikte artık escape_url yardımcısını şablon içerisinde kullanabilirsiniz:<br /><code class="html"><br /><a href="/book/{{ data.name|escape_url }}/{{ data.key }}">{{ data.name }}</a><br /></code><br /><br />register.filter ile fonksiyonumuzu yardımcı bir filtre olarak tanımladık. Eğer fonksiyonu bir etiket ile kullanmak istersek aşağıdaki yöntem işimizi görecektir. Bu yöntem için farklı bir fonksiyon geliştirelim. Mesela gelen parametreleri kullanıp geriye img kodunu göndersin:<br /><code class="python"><br />def create_image(image,alt):<br /> return '<img src="/media/images/%s" alt="%s" />' %(image,alt)<br /><br />register.simple_tag(create_image)<br /></code><br /><br />register.simple_tag ile kaydettiğimiz fonksiyonumuzun şablon dosyasındaki kullanımı ise şöyle olmalı:<br /><code class="html"><br />{% create_image "sample.png" "Örnek Açıklama" %}<br /></code><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Ömer Ücelhttp://www.blogger.com/profile/06991019782142366879noreply@blogger.com0tag:blogger.com,1999:blog-7247155306507171101.post-21048035875104526632009-04-24T14:04:00.000-07:002009-04-24T14:15:23.571-07:00Python’da Karakter Dizisi İşlemleri(<a href="http://www.gokmengorgen.net/gunluk/?p=229">http://www.gokmengorgen.net</a> adresinden alıntıdır.)<br /><br />Geçenlerde bir arkadaşım, Python 3′te <span style="font-weight:bold;">gettext</span> modülünün nasıl kullanılacağını sormuştu, ben de henüz 3.* sürümünü denemediğim için bir cevap verememiştim. Hala da verebilecek aşamada değilim; ama bu konu üzerinde biraz araştırma yaparken, ilginç bir internet sayfasıyla[<a href="http://www.python.org/dev/peps/pep-3101/">1</a>] karşılaştım. Aşağıda paylaşacağım kodların ve bilgilerin Python 2.* serisinde çalışmaması söz konusu olabilir.<br /><br />Python’da karakter dizilerini iki biçimde çağırabiliyoruz:<br /><ul><br /> <li>Karakter dizileri için % işleyicisi[<a href="http://docs.python.org/library/stdtypes.html#string-formatting-operations">2</a>].</li><br /> <li>string.Template modülü[<a href="http://docs.python.org/library/string.html#string.Template">3</a>]</li><br /></ul><br /><br /><span style="font-weight:bold;">%</span> işleyicisiyle kullanım örneği, Python belgelerinde verilmiş:<br /><br /><code class="python"><br />>>> print('%(language)s has %(#)03d quot types.' % {'language': "Python", "#": 2})<br />#Python has 002 quot types.<br /></code><br /><br />Bu kodda değişkenler bir sözlük içinde eşleştirilmekte ve print çıktısında tanımlanmış değerleriyle ekrana yazılmaktadır. Bunun aynısı şu şekilde de yapabilirdik:<br /><br /><code class="python"><br />>>> print('%s has %03d quot types.' % ("Python", 2))<br />#Python has 002 quot types.<br /></code><br /><br />Birincisine göre daha basit olsa da, birinci kodda şöyle bir avantaj söz konusudur:<br /><code class="python"><br />>>> print('The %(first)s variable, and the %(second)s variable.' % {'second': "New", 'first': "Old"})<br />#The Old variable, and the New variable.<br /></code><br /><br />Bu şekilde kullandığımız zaman, ikinci işleyiciyi ilk olarak tanımlayıp, ikinci işleyiciyi ise sonra tanımlayabilme fırsatımız olabiliyor. Nerelerde kullanılabileceği ayrı bir merak konusu. Bu merakı gidermeden önce bir de şu şekilde kullanıma bir bakalım:<br /><br /><code class="python"><br />>>> print('The {1} variable, and the {0} variable.'.format("New", "Old"))<br />#The Old variable, and the New variable.<br /></code><br /><br />İlginç, değil mi? Aslında bu kadar çeşitlilik olması garibime gidiyor; ama bu son yöntemin yüksek seviye programlama diline daha yakın bir tarz olduğunu düşünmeden edemiyorum. Yanılmıyorsam bu tip kullanım, C# ve Java’da da var. Şimdi son olarak aşağıdaki kodu inceleyelim:<br /><br /><code class="python"><br />import sys<br /> <br />class Main:<br /> def __init__(self):<br /> print("Python version is, {0}.".format(sys.version[:5])) # print'lerin yazimina dikkat..<br /> <br /> digits_list = self.digits()<br /> <br /> print("{1} is bigger than {0} as digit.".format(digits_list[0], digits_list[1]))<br /> <br /> def digits(self):<br /> try:<br /> first_digit = int(input("Please write a digit: ")) # raw_input yerine input kullaniliyor.<br /> second_digit = int(input("And second digit: "))<br /> <br /> except ValueError:<br /> print("\nSorry, you must enter a digit.")<br /> exit()<br /> <br /> return self.sort(first_digit, second_digit)<br /> <br /> def sort(self, x, y):<br /> return sorted([x,y])<br /> <br />if __name__ == "__main__":<br /> Main()<br /></code><br /><br />Kodun yaptığı şey basit: Sizden iki sayı girmeniz isteniyor ve sayıları, büyüklüklerine göre {0} ve {1} ile eşleştirip, “X, Y’den sayıca büyüktür.” gibisinden bir cümle döndürüyor. Kod basit olduğu için bu tip karakter dizisi işleyicilerin faydası pek belli olmuyor; ama mutlaka bir yerde faydası vardır =). Son kodun çıktısı şu şekilde:<br /><br /><code><br />[gkmngrgn@gacer ~]$ python3 rank.py<br />Python version is, 3.0.1.<br />Please write a digit: 3<br />And second digit: 1<br />3 is bigger than 1 as digit.<br />[gkmngrgn@gacer ~]$<br /></code><br /><br />[1]: <a href="http://www.python.org/dev/peps/pep-3101/">http://www.python.org/dev/peps/pep-3101/</a><br />[2]: <a href="http://docs.python.org/library/stdtypes.html#string-formatting-operations">http://docs.python.org/library/stdtypes.html#string-formatting-operations</a><br />[3]: <a href="http://docs.python.org/library/string.html#string.Template">http://docs.python.org/library/string.html#string.Template</a><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7247155306507171101.post-59235404941473248982009-03-27T05:35:00.001-07:002009-03-27T05:42:06.139-07:00Opencv Modülü İle Kamera Görüntüsü AlmaBu yazımızda python, <a href="http://sourceforge.net/projects/opencv/">opencv modülü</a> ve qt ile kamera görüntüsü alıp göstereceğiz, hatta resim de çekeceğiz.<br /><br /><code class="python"><br /># -*- coding: utf-8 -*-<br /><br />from PyQt4 import QtGui, QtCore<br /><br />import Image<br />import ImageQt<br />import opencv<br />from opencv import highgui<br /><br /># kamera yakalayıcı...<br />camera = highgui.cvCreateCameraCapture(0)<br /><br /># kamera işlemimiz sürekli olarak ekrana görüntüyü basıyor...<br />class camThread(QtCore.QThread):<br /> def run(self):<br /> while True:<br /> # görüntüleri basarken her aralıkda 60ms bekliyoruz, buda 60fps demek...<br /> # eğer sizde görüntü yavaş olursa yani fps yi düşürün...<br /> self.msleep(60)<br /> # görüntüyü alıyoruz...<br /> self.image = highgui.cvQueryFrame(camera)<br /><br /> # resim sinyalini yayıyoruz ve gidecek fonksiyona self.image değişkenini,<br /> # gönderiyoruz...<br /> self.emit(QtCore.SIGNAL("image"), (self.image))<br /><br />class camoruxWindow(QtGui.QMainWindow):<br /> def __init__(self):<br /> QtGui.QMainWindow.__init__(self)<br /><br /> self.resize(650, 450)<br /><br /> self.camThread = camThread()<br /><br /> self.showLabel = QtGui.QLabel(self)<br /> self.showLabel.resize(640, 480)<br /><br /> # camThread den gelen sinyali alıyoruz ve self.showImage ye bağlıyoruz...<br /> self.connect(self.camThread, QtCore.SIGNAL("image"), self.showImage)<br /> self.camThread.start()<br /><br /> self.button = QtGui.QPushButton(self)<br /> self.button.setText(u"Resim çek")<br /> self.connect(self.button, QtCore.SIGNAL("clicked(bool)"), self.cek)<br /><br /> def cek(self):<br /> # flash<br /> self.flash = QtGui.QWidget()<br /> self.flash.setStyleSheet("background-color: rgb(255, 255, 255);")<br /> self.flash.showFullScreen()<br /><br /> # resim çekiliyor...<br /> i = highgui.cvQueryFrame(camera)<br /> opencv.adaptors.Ipl2PIL(i).save("deneme.png")<br /><br /> # flash kapanıyor<br /> self.flash.close()<br /><br /> def showImage(self, image):<br /> # burada: gelen resmi ImageQt ile QLabel in istediği şekile dönüştürüyoruz...<br /> self.image = ImageQt.ImageQt(opencv.adaptors.Ipl2PIL(image).transpose(Image.FLIP_LEFT_RIGHT))<br /> # ve gösteriyoruz...<br /> self.showLabel.setPixmap(QtGui.QPixmap.fromImage(self.image))<br /><br />app = QtGui.QApplication([])<br />mw = camoruxWindow()<br />mw.show()<br />app.exec_()<br /></code><br /><span style="font-weight:bold;">Dikkat etmeniz gereken nokta şu:</span><br /><span style="font-style:italic;">camThread</span> görüntüyü gösterirken 60ms bekliyor yani 60fps ile görüntü gösteriliyor, sizde eğer görüntü yavaş olursa fps yi düşürmeniz gerekiyor demektir. <span style="font-style:italic;">30-40 fps</span> arası deneyin…<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Oğuzhan Eroğluhttp://www.blogger.com/profile/09142565628105212005noreply@blogger.com16tag:blogger.com,1999:blog-7247155306507171101.post-79515953682810981682009-03-19T15:36:00.000-07:002009-03-19T19:59:42.548-07:00PyGame İle İlerleme Çubuğu (ProgressBar) YapalımBugün pygame ile basit bir ilerleme çubuğu yapacağız. Uzun zaman alan işlemlerde kullanıcı sıkılmasın diye ekranda sürekli ilerleyen bir çubuk görmeye alışkınsanız bunu neden biz de yapamayalım diyor olabilirsiniz. Öyleyse bu yazı size göre.<br /><br />İlerleme çubuğu sınıfımız ProgressBar olacak. Bu sınıf görsel hazırlıklarını, miras aldığı ProgressImage'a yaptıracak. Kullanım için biraz ilkel olsa da başlangıç olarak basit bir yöntem seçtim. Ama bu yazının amacı sizlere pygame'i anlatmak. Kullanmanızı ve neden ben de yapmayayım demenizi sağlamak. Bu yüzden kullanılabilirlik konusunda yeterinden öte ayrıntıya girmedim.<br /><br />Örneğin uzun zaman alan bir döngünüz var:<br /><code class="python"><br />for i in range(kere):<br /> oturanboga.konus()<br /></code><br /><br /><br />Bu döngüde ProgressBar sınıfından bir nesneyi şu şekilde kullanacaksınız:<br /><code class="python"><br />bariscubugu = ProgressBar(kere, adim, cubukboyutu, ilkrenk, sonrenk) <br />while not bariscubugu.isEnd():<br /> oturanboga.konus()<br /> bariscubugu.makestep()<br /></code><br /><br />Bu kadarı bile sizleri harekete geçirmiştir sanırım. Şimdi yapıma geçelim :)<br /><br />Önce meşhur modülümüzü import edelim ve bakalım internetten indirmiş misiniz ya da pisi paket yöneticinizden yüklemiş misiniz:<br /><br /><code class="python"><br />import sys<br />try:<br /> import pygame<br />except ImportError:<br /> print '''<br /> This Program Needs Pygame module to be installed.<br /> For windows you can download it from this adress:<br /> http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi<br /> For linux this adress will be helpful:<br /> http://pygame.org/ftp/pygame-1.8.1release.tar.gz<br /> '''<br /> sys.exit(0)<br /></code><br /><br />Burada try bloğu içinde yer alan ifade("import pygame") test edilir; hata varsa except bloğunda verilen hataya bakılır. Hatalar uyuşuyorsa except bloğu çalıştırılır; traceback ile başlayan soğuk cümleler yerine bizim programımızda yer alan kullanıcı dostu arkadaş cümleler kullanılabilir ve kullanıcının yüreği ferah tutulmuş olur.<br /><br />Kök sınıfımız(miras veren sınıf) ProgressImage'ı yazmaya başlayalım:<br /><br /><code class="python"><br />class ProgressImage:<br /> def __init__(self, size, initcolor, barcolor):<br /> pygame.display.init() #1.<br /> self.screen = pygame.display.set_mode(size) #2.<br /> self.bar = pygame.Surface((size[0]-10,size[1]-10)) #3.<br /> self.bar.fill(initcolor) #4.<br /> pygame.display.update(self.screen.blit(self.bar, (5,5))) #5.<br /><br /> def quit(self):<br /> pygame.display.quit()<br /></code><br /><br /><ol><br /><li>Bu sınıfı iyi inceleyelim. Pygame bilenler ne yapıldığını aşağı yukarı anlayacaklardır ama bilmeyen ya da az bilenler için açıklayalım:<br />pygame.display.init() satırı display modülünü başlangıçlandırır. Değer döndürmez. Bu metod kullanılmadan önce pygame.display.SDL_VIDEODRIVER ortam değişkeninin -eğer isteniyorsa- değiştirilmesi mümkündür. Böylece kullanılacak video sürücüsü seçilebilir. (Ayrıntı için <a href="http://www.pygame.org/docs/ref/display.html#pygame.display.init">bakınız</a>)<br /><br /><li><a href="http://www.pygame.org/docs/ref/display.html#pygame.display.set_mode">pygame.display.set_mode()</a> metodu görüntüyü ayarlar ve 3 argüman alır. Bize sadece iki tanesi hatta biri gerekecek. İlk argüman genişlik ve yükseklik değerlerini içeren bir sabit listedir.(tuple) Burada (genislik, yukseklik) şeklinde geçecektir. İkinci argüman flags parametresidir. Bu da görüntü modunu seçmeye yarar. Kodumuzda size parametresiyle yetinilmiştir. Bu metod geriye bir Surface nesnesi döndürür.<br /><ul><br /><li>Surface görüntüleri pixeller halinde saklayan bir nesnedir.<br /><li>Yeni bir nesne oluştururken tual = pygame.Surface((100,100)) şeklinde kullanılabilir. Bu tual isminde bir yüzey nesnesi oluşturacaktır.<br /><li>Örneğimizde <code class="python">self.screen = pygame.display.set_mode(size)</code> kodu screen isminde bir Surface nesnesini display modülünün ilk kez oluşturduğu ana ekrandan almaktadır.<br /><li>screen artık ana ekrana referans etmektedir.<br /></ul><br /><br /><li><code class="python">self.bar = pygame.Surface((size[0]-10,size[1]-10))</code><br />satırında da az önce gördüğümüz gibi bir Surface nesnesi yaratılmaktadır. Bu nesneyi screen ana ekranının üzerine çizeceğiz; çünkü bu nesne göstergemizin görüneceği nesne olacak(siz buna katman(layer) da diyebilirsiniz). Göstergenin boyutu screen nesnesinin boyutuna göre 5 piksel içerde görünecek.<br /><br /><li><code class="python">self.bar.fill(initcolor)</code> satırında elde ettiğimiz bar isimli yüzey nesnesini initcolor rengiyle dolduruyoruz. Burada color hakkında şunu söylemeliyim: Kırmızı(red), Yeşil(green), Mavi(blue) değerlerini 0-255 değerleri arasında içeren bir üçlü sabit listedir color. (0,0,255) gibi(mavi)<br /><br /><li><code class="python">pygame.display.update(self.screen.blit(self.bar, (5,5)))</code> satırında önce pygame.display.update() metoduna verilen parametreye bakalım.<br /><ul><br /><li>self.screen.blit(self.bar, (5,5)) komutu <strong>bar</strong> nesnesini screen nesnesinin üzerine çizer. Ama bunu ekrana yansıtmaz. Dikkat: nesneleri üstüste bindirir ancak görüntünün oluşması için update() metodu çalışmaldır.<br /><li>Bu metod yani <strong>blit()</strong> metodu Rect döndürür. Bu bar nesnesinin kapladığı dikdörtgen alanın koordinatlarını içeren başka bir nesnedir ki tahmin edeceğiniz gibi pygame.display.update() metodu Rect alır.<br /><li>Sonuç olarak yaptığımız ana ekran nesnesi olan screen'in üzerine bar nesnesini yanlızca kapladığı alan içinde bindirmektir. Bu bütün ekranı güncellemekten daha hızlı bir metoddur.<br /></ul><br /></ol><br /><br />Bu kadarı pygame için yeterli sanırım şimdi programı huzurlarınıza sunuyorum. Sizde programı dilediğiniz gibi kopyalayıp kendi başınıza birşeyler deneyebilirsiniz. <br /><br /><code class="python"><br />import sys<br />try:<br /> import pygame<br />except ImportError:<br /> print '''<br /> This Program Needs Pygame module to be installed.<br /> For windows you can download it from this adress:<br /> http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi<br /> For linux this adress will be helpful:<br /> http://pygame.org/ftp/pygame-1.8.1release.tar.gz<br /> '''<br /> sys.exit(0)<br /><br />class ProgressImage:<br /> def __init__(self, size, initcolor, barcolor):<br /> pygame.display.init()<br /> self.screen = pygame.display.set_mode(size)<br /> self.bar = pygame.Surface((size[0]-10,size[1]-10))<br /> self.bar.fill(initcolor)<br /> pygame.display.update(self.screen.blit(self.bar, (5,5)))<br /> <br />class ProgressBar(ProgressImage):<br /> def __init__(self, whole, step, size, initcolor, barcolor):<br /> ProgressImage.__init__(self, size, initcolor, barcolor)<br /> self.size = size<br /> self.initcolor = initcolor<br /> self.barcolor = barcolor<br /> self.whole = whole<br /> self.step = step<br /> if whole < step:<br /> print "Error: ProgressBar length can't be smaller than step"<br /> sys.exit(1)<br /> self.slice = float(step)/float(whole)<br /> self.percent = 0.0<br /><br /> def showprogress(self):<br /> self.screen.fill(self.initcolor)<br /> barwidth = (self.size[0]-10)*self.percent<br /> barheight = self.size[1]-10<br /> self.bar = pygame.Surface((barwidth,barheight))<br /> self.bar.fill(self.barcolor)<br /> pygame.display.update(self.screen.blit(self.bar, (5,5)))<br /><br /> def reset(self):<br /> self.percent = 0.0<br /> self.showprogress()<br /> <br /> def makestep(self):<br /> if self.percent < 1.0:<br /> self.percent += self.slice<br /> self.showprogress()<br /><br /> def quit(self):<br /> pygame.display.quit()<br /><br /> def isEnd(self):<br /> if self.percent<=1.0:<br /> return False<br /> else:<br /> return True<br /> <br />if __name__ == "__main__":<br /> pb = ProgressBar(1000, 10, (100,40), (255,255,255), (0,0,255))<br /> i, j, k = 0, 0, 0<br /> while not pb.isEnd():<br /> temp = "running.."<br /> for j in range(5):<br /> for k in range(5):<br /> print temp<br /> pb.makestep()<br /> pb.quit()<br /></code><br /><br /><a href="http://picasaweb.google.com.tr/dr.ozgur.sonmez/BloggerResimler?authkey=Gv1sRgCJfwv9_W_NuTvAE&feat=directlink" target="_blank">progressbar.png</a><br />Hepinize kolay gelsin :)<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Anonymousnoreply@blogger.com2tag:blogger.com,1999:blog-7247155306507171101.post-27562984315835648382009-02-22T02:37:00.000-08:002009-02-22T02:37:22.194-08:00Listenin kopyasını almakPython da her eşitlik referans gösterir. Bu iddalı lafın anlamını şöyle ifade edeyim.<br />
Örneğin şekildeki gibi bir liste = başka bir liste şeklinde kopya almaya çalıştığınızda şöyle bir gariplik (aslında güzellik) ile karşılaşırsınız.<br />
<br />
<code class="python">>>> a = ["a","b","c"]<br />
>>> b = a<br />
>>> b.append("d")<br />
>>> print a, b<br />
['a', 'b', 'c', 'd'] ['a', 'b', 'c', 'd']</code><br />
<br />
Nesnelere gelince yine aynı mantık, nesne = başkabirnesne dediğinizde referans göstermiş oluyorsrunuz :<br />
<br />
<code class="python"><br />
>>> class obj:<br />
... def __init__(self):<br />
... self.counter = 0<br />
... def inc(self):<br />
... self.counter += 1<br />
... <br />
>>> a = obj()<br />
>>> b = a<br />
>>> a.inc()<br />
>>> print a.counter<br />
1<br />
>>> print b.counter<br />
1</code><br />
<br />
Bir nesnenin ya da değişkenin kopyasını almak istediğinizde çeşitli yöntemler var, sanırım verilerin (list, tuple, dict vs) kopyasını alırken karşılaştığım en yakışıklı yöntem şu :<br />
<br />
<code class="python">>>> a = ["a","b","c"]<br />
>>> b = list(a)<br />
>>> print a , b<br />
['a', 'b', 'c'] ['a', 'b', 'c']<br />
>>> a.append("d")<br />
>>> print a, b<br />
['a', 'b', 'c', 'd'] ['a', 'b', 'c']</code><br />
<br />
Peki bir nesnenin kopyasını almak istiyorsak? bunun için copy adında bir modül yapmışlar :<br />
<br />
<code class="python">>>> class obj:<br />
... def __init__(self):<br />
... self.counter = 0<br />
... def inc(self):<br />
... self.counter += 1<br />
... <br />
>>> a = obj()<br />
>>> from copy import copy<br />
>>> b = copy(a)<br />
>>> a.inc()<br />
>>> b.inc()<br />
>>> b.inc()<br />
>>> b.inc()<br />
>>> print a.counter, b.counter<br />
1 3</code> Eğer copy modülünden deepcopy fonksionunu import eder kullanırsak, nesneyi özyinelemeli olarak kopyalıyormuş. Herkese iyi hafta sonları<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com0tag:blogger.com,1999:blog-7247155306507171101.post-76802607284471957032009-02-17T15:10:00.000-08:002009-02-17T15:16:07.018-08:00Django'da ImageField'ı kayıt esnasında yeniden adlandırmak.Elimde şu şekilde bir model var :<br />
<br />
products/models.py<br />
<code class="python">class Product(models.Model):<br />
type = models.PositiveSmallIntegerField(choices = PRODUCT_TYPES,)<br />
category = models.ForeignKey(Category)<br />
name = models.CharField(max_length=50)<br />
slug = models.SlugField()<br />
<br />
image = models.ImageField(upload_to = "product_images")<br />
def __unicode__(self):<br />
return self.name</code><br />
<br />
Yapmak istediğim ise şu : yönetici panelinde bu modeli kaydederken verilen dosyanın soyadı değişmeden isminin slugfield olarak değiştirilip kaydedilmesi.<br />
<br />
Örnek vermek gerekirse adı "Vestel Cep Televizyonu" olan bir ürünü image alanı img13.jpg dosyası ile kaydettiğimi düşünelim. Bu durumda image, "product_images/vestel-cep-televizyonu.jpg" olarak kaydedilmeli (soyadı olan jpg aynı kalıyor, dosyanın adı slug ile eşitleniyor)<br />
<br />
Bunu yapabilmek için düşünmeye başladığımda admin site'sinin, save_model fonksiyonunu override edebildiğimizi öğrendim ve şöyle bir şey yazdım :<br />
<br />
<code class="python">from os.path import dirname, join, splitext<br />
from shutil import move as rename<br />
<br />
class ProductAdmin(admin.ModelAdmin):<br />
prepopulated_fields = {"slug": ("name",)} <br />
def save_model(self, request, obj, form, change):<br />
extension = splitext(obj.image.path)<br />
new_image_path = join(dirname(obj.image.path), obj.slug + extension)<br />
rename(obj.image.path, new_image_path)<br />
obj.image.path = new_image_path<br />
obj.save()</code><br />
<br />
Fakat bu şöyle bir hataya yol açıyordu : <br />
<br />
<code class="python">File "/home/horselogy/django/mobil8/../mobil8/products/admin.py" in save_model<br />
36. obj.image.path = new_image_path<br />
<br />
Exception Type: AttributeError at /admin/products/product/2/<br />
Exception Value: can't set attribute</code><br />
<br />
Saatlerce path değişkenini set edemiyorum diye saç baş yolduktan sonra fark ettim ki tek yapmam gereken obj.image = "uploaded/path" şeklinde yolu göstermem. Çünkü name ve path değerleri bu şekilde otomatik olarak set ediliyor. Neyse son hali ile şu şekilde olayı gerçekleştirdim<br />
<br />
products/admin.py<br />
<code class = "python">class ProductAdmin(admin.ModelAdmin):<br />
prepopulated_fields = {"slug": ("name",)}<br />
def save_model(self, request, obj, form, change):<br />
extension = splitext(obj.image.path)[-1]<br />
new_image_name = obj.slug + extension<br />
new_path = join(dirname(obj.image.path), new_image_name)<br />
rename(obj.image.path,new_path)<br />
obj.image = join("product_images", new_image_name)<br />
obj.save()</code><br />
<br />
Bir dili anlarken çok zor bir dönem geçer, en aptal şey için bile saatlerinizi harcarsınız. Sonrası çorap söküğü gibi gelir her şey kolaylaşır. Sanırım bende Django konusunda bu dönemden geçiyorum. Sizin dönemlerinizin sancısız olmasını diliyor yazıyı burada bitiriyorum :).<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com5tag:blogger.com,1999:blog-7247155306507171101.post-78716305033182148272009-01-31T05:14:00.000-08:002009-01-31T05:24:57.549-08:00Django Kullanıcı Profilleri<div>Django ile uygulama geliştirirken kullandığımız User modelinde username, first_name, last_name, email, password, is_staff, is_active, is_superuser, last_login, date_joined alanları bulunmakta. Çoğu proje için bu alanlar bize yetsede, ek alanlara büyük ölçüde ihtiyaç duyabiliyoruz. Böyle durumlarda yine User modeli içindeki get_profile() methodu işimizi kolaylaştırmaktadır.</div><br /><br /><div>Bu methodu kullanabilmek için öncelikle settings.py dosyamıza aşağıdaki eklemeyi yapmamız gerekmekte:</div><br /><br /><code class="python"><br />[...]<br />INSTALLED_APPS = (<br /> 'django.contrib.auth',<br /> 'django.contrib.contenttypes',<br /> 'django.contrib.sessions',<br /> 'django.contrib.sites',<br /> 'django.contrib.admin',<br /> 'projectname.users'<br />)<br /><br />AUTH_PROFILE_MODULE = 'users.UserProfile'<br /></code><br /><br /><div>users uygulama adı, UserProfile ise bu uygulama içinde tanımlanan bir veritabanı modeli adını belirtmektedir. Şimdi bu modelimizi yazalım ve ardından syncdb ile değişiklikleri veritabanımıza yansıtalım:</div><br /><br /><code class="python"><br />from django.contrib.auth.models import User<br /><br />class UserProfile(models.Model):<br /> user = models.ForeignKey(User, unique=True)<br /> telefon = models.CharField(max_length=15)<br /></code><br /><br /><div>Bu modeli kullanıcı kaydı sırasında aşağıdaki şekilde kullanabilir ve oluşan kullanıcı için bir profil oluşmasını sağlayabilirsiniz:</div><br /><br /><code class="python"><br />from projectname.users.models import UserProfile<br /><br />[...]<br />user = User.objects.create_user(username,'',password)<br />user.is_staff = True<br />user.is_active = True<br />user.save()<br />[...]<br /><br />profile = UserProfile(user=user,telefon=telefon)<br />profile.save()<br /></code><br /><br /><div>Kullanıcı bilgilerinin düzenlenmesi işleminde ise aşağıda kod profildeki bilgilerin güncellenmesini sağlayacaktır:</div><br /><br /><code class="python"><br />profile = request.user.get_profile()<br />profile.telefon = telefon<br />profile.save()<br /></code><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Ömer Ücelhttp://www.blogger.com/profile/06991019782142366879noreply@blogger.com0tag:blogger.com,1999:blog-7247155306507171101.post-79878551102507954492009-01-18T09:48:00.000-08:002009-01-18T10:11:41.327-08:00Erime efekti.Malum sınav zamanı yazacak hiç vaktim yok fekat şu spor olsun diye yaptığım çalışmayı yayınlamadan edemedim. Kod çok kısa ve çok açık. Sıkı bir inceleme ile ne yaptığı anlaşılabilir. Hatta bu bulmacamsı bir yazı olsun, siz çözün nasıl çalıştığını :)<br /><br /><object width="438" height="438"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2870963&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2870963&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="438" height="438"></embed></object><br /><a href="http://vimeo.com/">reverse melting effect made with python and pygame - 2</a> from <a href="http://vimeo.com/user939947">Mirat Can Bayrak</a> on <a href="http://vimeo.com">Vimeo</a>.<br /><br /><code class="python">from pygame import surfarray, display, image<br />from random import choice<br />from os.path import join <br />class Screen:<br /> def __init__(self,name,resolution):<br /> display.set_mode(resolution,0,24)<br /> display.set_caption(name)<br /> self.surface = display.get_surface()<br /> self.width, self.height = resolution<br /><br />def blurize(surfarray):<br /> for y in range(2,len(surfarray)-2):<br /> for x in range(2,len(surfarray[y])-2):<br /> surfarray[x][y] = surfarray[x + choice((-1,0,+1))][y + choice((-1,0,+1))]<br />res = (440,440) # it must be same as image size<br />screen = Screen('Rendering...',res) # i want a screen<br />img = image.load("melt.jpg") # load image<br />screen.surface.blit(img,(0,0))<br />array = surfarray.pixels3d(screen.surface) # create array from it<br />display.update() # update my view<br />frames = 400 # num of frames to render<br />for frame in range(frames):<br /> image.save(surfarray.make_surface(array), join("output/" ,str(frames-frame) + ".png"))<br /> if frame > 25 :<br /> # do not blurize on first 25 frames<br /> blurize(array)<br /> display.update()<br /> print frame ,"th frame rendered"<br /></code><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-25213444697446355172009-01-05T12:56:00.000-08:002009-01-07T14:11:37.044-08:00Tkinter ile Bir Deneme: Sözcükleri Çoğul YapmaMerhaba Arkadaşlar;<br />Bugün küçük bir form penceresi oluşturacağız. Penceremizde iki metin girdisi(Entry), iki etiket(Label), bir adet düğme(Button) olacak. Programımız form aracılığı ile birinci metin girdisinden alacağı türkçe kelime girdisini ikinci metin girdisinde çoğul olarak gösterecek. Ve üstelik bunların hepsini Python ile ve komut satırından çıkmadan yapacağız.<br /><br />Önce program çekirdeğini oluşturacak "plurize(word)"(cogulyap(kelime)) metodunu yazalım. Bu metod word katarını(string) alır ve çoğul olan kelimeyi( : word + postfix) döndürür. Bunun için türkçedeki kurallara bir bakalım:<br />Türkçede son hecesi ince(e,i,ö,ü) sesli(vowel) olan kelimelere 'ler' eki(postfix) eklenir.<br />Son hecesi kalın(a,ı,o,u) sesli(vowel) olan kelimelere 'lar' eki(postfix) eklenir.<br />Türkçede heceler dört harfli ise sesli harf(vowel) baştan ikinci harftir.<br />Türkçede üç sessiz harf yanyana gelmez.<br /><br />Şimdi bu kurallara göre bir fonksiyon oluşturalım. Daha sonra kullanıcı arayüzünü(user interface) oluşturmaya geçeceğiz.<br /><br />Bunun için önerdiğim çözüm şöyle başlıyor:<br /><br /><code class="python"><br />vowelMatrix = {<br /> 'back': {'vowels' : (a, ı, o, u), 'postfix': 'lar'}<br /> 'front': {'vowels' : (e, i, ö, ü), 'postfix': 'ler'}<br /> }</code><br /><br />Bu sözlük yapısı bize arama ve karşılaştırma yaparken lazım olacak. Burada;<br />vowelMatrix['back'] = {'vowels' : (a, ı, o, u), 'postfix': 'lar'}<br />vowelMatrix['front'] = {'vowels' : (e, i, ö, ü), 'postfix': 'ler'}<br />vowelMatrix[0][vowels][3] = u<br /><br />Fonksiyonumuzu yazalım:<br /><br /><code class="python"><br />def plurize(self, word):<br /> '''Dört ya da daha fazla harften oluşan kelimelerde geçerlik sınaması yapar.<br /> wordü çoğul yapar ve döndürür'''<br /> isValid = None<br /> letters = list(word) #harfler<br /> backVowels = self.vowelMatrix['back']['vowels']<br /> frontVowels = self.vowelMatrix['front']['vowels']<br /> triad = letters[:3] #üçlü harf listesi<br /> if len(letters) > 4:<br /> #Dört sesten uzun kelimeler için<br /> for letter in letters: # geçerli bir sözcük mü<br /> if letter == ' ': # içinde boşluk içeriyorsa<br /> return None # Hata.<br /> for l in triad: # Üç sessiz harf ardarda geliyor mu<br /> if (l in backVowels) or (l in frontVowels):<br /> #üçlüdekilerden biri bile sesli ise geçerli.<br /> isValid = True<br /> break #tamam kelime geçerli<br /> else:<br /> #yoksa geçersizdir<br /> isValid = False<br /> if isValid:<br /> #kelimede sesli harf varsa<br /> tetrad = []*4 #geçici dörtlü<br /> tetrad[:3] = triad #ilk üç sesi üçlüden<br /> tetrad.append(letter) #dördüncü sesi sıradaki sesten aldık<br /> triad = tetrad[1:] #son üç sesi üçlüye yükledik<br /> else:<br /> #üç sessiz ardarda gelmiş.<br /> return None #Hata.<br /> #Kelime geçerli.<br /> #Şimdi çoğul yapma algoritması:<br /> if (letters[-1] in backVowels) or (letters[-2] in backVowels):<br /> #Sondan birinci harf ya da ikincisi kalın ise..<br /> #kelimeye uygun eki(postfix) yani 'lar' ekini ekle ve döndür<br /> return word + self.vowelMatrix['back']['postfix']<br /> elif (letters[-1] in frontVowels) or (letters[-2] in frontVowels):<br /> #Sondan birinci harf ya da ikincisi ince ise..<br /> #kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür<br /> return word + self.vowelMatrix['front']['postfix']<br /> elif len(letters) == 4:<br /> # 4 harfli ise 2. harfi sesli olabilir; 2. 4. sesi sesli olabilir;<br /> # 2. 3. sesi 'a' olabilir:<br /> if ((letters[0] not in backVowels) or (letters[0] not in frontVowels)) \<br /> and ((letters[2] not in backVowels) or (letters[2] not in frontVowels)) \<br /> and ((letters[3] not in backVowels) or (letters[3] not in frontVowels)) \<br /> and ((letters[1] in backVowels) or (letters[1] in frontVowels)):<br /> #1.3.4. sesler sessiz; 2. ses sesli ise(kask, türk gibi)<br /> return letters[1] in backVowels \<br /> and word + self.vowelMatrix['back']['postfix'] \<br /> or word + self.vowelMatrix['front']['postfix']<br /> elif (letters[1] == 'a') and (letters[2] == 'a'):<br /> #2. ve 3. ses 'a' ise(saat, maaş gibi)<br /> #kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür<br /> return word + self.vowelMatrix['front']['postfix']<br /> elif ((letters[1] in backVowels) or (letters[1] in frontVowels)) \<br /> and ((letters[3] in backVowels) or (letters[3] in frontVowels)):<br /> #2. 4. sesler sesli ise(pepe, lapa gibi)<br /> return letters[1] in backVowels \<br /> and word + self.vowelMatrix['back']['postfix'] \<br /> or word + self.vowelMatrix['front']['postfix']<br /> elif letters[3] in frontVowels:<br /> #4. sesli ince ise<br /> #kelimeye uygun eki(postfix) yani 'ler' ekini ekle ve döndür<br /> return word + self.vowelMatrix['front']['postfix']<br /> else:<br /> #kelime geçersizse<br /> return None #Hata.<br /> elif len(letters) == 3:<br /> #3 harfli ise salt 2. harfi sesli olabilir;<br /> #ya da salt 1. ve 3. sesler sesli olabilir:<br /> if (letters[1] in backVowels) or (letters[1] in frontVowels) <>\<br /> ~( (letters[0] in backVowels or letters[0] in frontVowels) \<br /> and (letters[2] in backVowels or letters[2] in frontVowels) ):<br /> #1. ve 3. ses sessiz, 2. ses sesli ise ya da tersi<br /> if (letters[1] in backVowels) or (letters[1] in frontVowels):<br /> #2. ses sesli ise<br /> #kelimeye uygun eki(postfix) ve döndür<br /> return letters[1] in backVowels \<br /> and word + self.vowelMatrix['back']['postfix'] \<br /> or word + self.vowelMatrix['front']['postfix']<br /> else:<br /> #2. ses sessiz ise<br /> #kelimeye uygun eki(postfix) ve döndür<br /> return letters[2] in backVowels \<br /> and word + self.vowelMatrix['back']['postfix'] \<br /> or word + self.vowelMatrix['front']['postfix']<br /> else:<br /> #kelime geçersizse<br /> return None #Hata.<br /> elif len(letters) == 2:<br /> #2 harfli ise ya birinci harf sesli ikincisi sessizdir ya da tersi<br /> if not ( ((letters[0] in backVowels) or (letters[0] in frontVowels)) <> \<br /> ((letters[1] in backVowels) or (letters[1] in frontVowels)) ):<br /> #iki ses de sesli ya da iki ses de sessiz ise hata. (aa, kk)<br /> return None<br /> elif ( (letters[0] in backVowels or letters[0] in frontVowels) <> \<br /> ~(letters[1] in backVowels or letters[1] in frontVowels) ):<br /> #ya birinci harf sesli ikincisi sessizdir ya da tersi(ka, ak)<br /> return (letters[0] in backVowels or letters[1] in backVowels) \<br /> and word + self.vowelMatrix['back']['postfix'] \<br /> or word + self.vowelMatrix['front']['postfix']<br /> else:<br /> #Başka olasılık kalmadı; ama denemeye değer:<br /> return None<br /> elif len(letters) == 1 or word == None:<br /> return None</code><br /><br />Burada yapılan işlem yukarıda sıraladığım kuralları program mantığına uyarlamak. Sırasıyla 4 sesten büyük, 4 sesli, 3 sesli, 2 sesli ve 1 sesli durumları sınandı.<br /><br />Dialog Sınıfını yazarken bu fonksiyonu(işlevi) def plurize(self, word)<br />şeklinde ekleyeceğiz. Tkinter ile kullanıcı arayüzü(user interface) içeren uygulamalar yazmak için öncelikle kodumuza uygun modülleri "import" etmeliyiz:<br /><br /><code class="python"># -*- coding: utf-8 -*-<br />#!usr/bin/python<br />from Tkinter import *</code><br /><br />Bu kod ile Tkinter modülünden bütün sınıfları içerdik(import, include). Artık örneğin Label sınıfını kullanırken "Tkinter.Label" şeklinde açımlamak zorunda kalmayacağız. Doğrudan "Label" şeklinde açımlama(decleration) yapabileceğiz.<br />Şimdi sınıf mantığı ile Tkinter nasıl birleştirilir onu görelim. Bir etiket yapmak o kadar kolay değil; belki de çok kolay ;)<br /><br /><code class="python">class PlurizeDialog:<br /> def __init__(self, master):<br /> pass</code><br /><br />Burada PlurizeDialog isimli bir sınıf tanımladık. Bu bizim UI(user interface : kullanıcı arayüzü) sınıfımız. Bu sınıfın yapıcısı(constructor) __init__() işlevi. Bu işleve dikkat:<br /><br /><code class="python">def __init__(self, master):</code><br /><br />Bu kod içinde yer alan master parametresi root = Tk() ile yaratacağımız ana pencerenin referansını alacak. Yani<br /><code class="python">root = Tk()<br />pl = PlurizeDialog(root)</code><br />diyebilmek için master parametresini kullanıyoruz.<br />Geri kalan işlemler basit:<br /><code class="python"><br /> Label(master, text='Enter Turkish:').pack()<br /> self.e1 = Entry(master)<br /> self.e1.pack(padx=18)<br /> Label(master, text='Plural:').pack(pady=3)<br /> self.e2 = Entry(master)<br /> self.e2.pack(pady=3, padx=18)<br /> b = Button(master, text='Plurize', command=self.show_plurize)<br /> b.pack(pady=9)</code><br />kodu ile __init__() bitiyor. Burada yaptığımız Label ile iki tane etiket oluşturmak. Entry ile iki metin girdisi oluşturmak, Button ile bir düğme eklemek. Burada command=show_plurize atamasına dikkat. Düğmeye tıklandığında çalışacak olan show_plurize() şimdi geliyor:<br /><code class="python"><br /> def show_plurize(self):<br /> word = self.e1.get()<br /> newWord = self.plurize(word)<br /> if newWord != None:<br /> self.e2.insert(0, newWord)<br /> else:<br /> self.e2.insert(0, "Invalid Word!")<br /></code><br /><br />Burada b düğmesine tıklandığında çalışacak işlev görülüyor. plurize() işlevini kullanan bu işlev sayesinde kod kısmı ile ui kısmını ayırmış olduk.<br /><br />İşte Dialog Sınıfı ve programın son hali:<br /><br /><code class="python"><br /># -*- coding: utf-8 -*-<br /><br />from Tkinter import *<br /><br />class PlurizeDialog:<br /> def __init__(self, master):<br /> Label(master, text='Enter Turkish:').pack()<br /> self.e1 = Entry(master)<br /> self.e1.pack(padx=18)<br /> Label(master, text='Plural:').pack(pady=3)<br /> self.e2 = Entry(master)<br /> self.e2.pack(pady=3, padx=18)<br /> b = Button(master, text='Plurize', command=self.show_plurize)<br /> b.pack(pady=9)<br /> vowelMatrix = { \<br /> 'back': {'vowels' : ('a', 'ı', 'o', 'u'), 'postfix': 'lar'}, \<br /> 'front': {'vowels' : ('e', 'i', 'ö', 'ü'), 'postfix': 'ler'} \<br /> }<br /> def show_plurize(self):<br /> word = self.e1.get()<br /> newWord = self.plurize(word)<br /> if newWord != None:<br /> self.e2.insert(0, newWord)<br /> else:<br /> self.e2.insert(0, "Invalid Word!")<br /> def plurize(self, word):<br /> pass #yukarıda verildi.<br /> <br />if __name__ == '__main__':<br /> root = Tk()<br /> pd = PlurizeDialog(root)<br /> root.mainloop()</code><br /><br />İyi Çalışmalar.<br />Özgür Sönmez.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Anonymousnoreply@blogger.com7tag:blogger.com,1999:blog-7247155306507171101.post-82088756260010048662008-12-28T17:53:00.000-08:002008-12-28T18:05:40.743-08:00Python 3.0'da Söz Dizimi Değişiklikleri: Öznitelik İçin Açıklamalar (Attribute Annotations)<span style="font-style:italic;">(Arkadaşlar merhaba. Bugün Özgür Sönmez arkadaşımız eposta yoluyla, Python 3.0'daki söz dizimi değişiklikleriyle ilgili nefis bir yazı, hatta sitemizin ismine uygun bir şekilde tabiri caizse nefis bir deneyim paylaşımında bulundu, ben de aynı şekilde buraya aktarıyorum. Sorularınız için yorumlarınızı bekleriz.)</span><br /><br />Python 3000'de birçok değişiklik var; bunlardan biri de sözdizimindeki değişiklikler. Bugün burada özniteliklere açıklama eklemenin python 3000'de ne kadar kolay ve göze hitap eden bir biçimde yapılabildiğini göreceğiz. Öyle ki, açıklamalar artık string (katar) olmak zorunda bile değil:<br /><br /><code class="python"><br />def Toplam (x: "Toplanacak Birinci Sayı", y: "Toplanacak İkinci Sayı") -> "Toplamın Sonucu":<br /> ...<br /></code><br /><br />ifadesi;<br /><code class="python"><br />def Toplam (x,y):<br /> ...<br /></code><br /><br />ifadesi ile fonksiyonel olarak aynı. Ancak python içinde bir kodda bu metodun <span style="font-weight:bold;">__annotation__</span> özniteliğini kullanırsanız şu şekilde bir sözlük alırsınız:<br /><br /><code class="python"><br />{'x': 'Toplanacak Birinci Sayı'<br /> 'y': 'Toplanacak İkinci Sayı'<br /> 'return': 'Toplamın Sonucu'<br />}<br /></code><br /><br /><a href="http://python.org">python.org</a>'da söylendiğine göre bu yenilik bir framework ya da metaclass deneyimini cesaretlendirmek için getirilmiş bir açıklama standardizasyonu. Örnekte de gördüğümüz gibi bu yenilik gerçekten göz kamaştırıcı. Öyle ki, py'ciler bununla kalmamışlar, örneğin:<br /><br /><code class="python"><br />def StoktanGetir(malzeme: "Getirilecek malzemenin adı", no: "Getirilecek malzemenin no'su" = 1):<br /> ...<br /></code><br /><br />ifadesinde olduğu gibi. Açıklamaları eklerken varsayılan parametreden de vazgeçilmemiş. Üstelik en önemlisi açıklamalar fonksiyon parantezlerinin içinde yer alıyor. Bir başka belirtmek istediğim şey de açıklamaların katar olma zorunluluğunun olmaması. Bir sözlük yapısında olduğu için __annotations__ içinde değer olarak giren açıklamalar her türden olabilir.<br />Anlaşılıyor ki bundan böyle fonsiyonlarımızı şöyle yazacağız:<br /><br /><code class="python"><br />def aligel(x: "Nereye (string)",<br /> y: "Kentkartım doluysa true, değilse false (bool)") -> "Gelebilecekse true, gelemeyecekse false":<br /></code><br /><br />İyi Çalışmalar.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-76015838393726620732008-12-10T11:36:00.000-08:002009-01-22T00:35:25.818-08:00PyGame hakkında<a href="http://www.pygame.org/">Pygame</a>, Python kullanıcıları rahatça oyun geliştirebilsin diye Pete Shinners tarafından geliştirilmeye başlanmış bir Python pakedi. İçerisinde şu modüller ile birlikte geliyor :<br /><ul><li>Cdrom (manage cdrom devices and audio playback)<br /></li><li>Cursors (load cursor images, includes standard cursors)</li><li>Display (control the display window or screen)<br /></li><li>Draw (draw simple shapes onto a Surface)<br /></li><li>Event (manage events and the event queue)<br /></li><li>Font (create and render Truetype fonts)<br /></li><li>Image (save and load images)</li><li>Joystick (manage joystick devices)<br /></li><li>Key (manage the keyboard)</li><li>Mouse (manage the mouse)<br /></li><li>Mask<br /></li><li>Mixer<br /></li><li>Movie (playback of movies)<br /></li><li>Music (playback of music)<br /></li><li>Overlay<br /></li><li>Pixelarray<br /></li><li>Rect<br /></li><li>Sndarray<br /></li><li>Sprite<br /></li><li>Surface<br /></li><li>Surfarray (manipulate images with Numeric)<br /></li><li>Time (control timing)<br /></li><li>Transform (scale, rotate, and flip images)<br /></li></ul>Görüldüğü üzere zenginlik konusunda karun kadar zengin PyGame. Avantajlarının biri de geliştirdiğiniz uygulamanın diğer işletim sistemlerine kolayca port edilebilmesi. Hatta işleme gerek kalmaksızın Mac sistemlerde direkt olarak çalışıyor.<br /><br />Bu pakedi kullanarak geliştirdiğiniz ürünleri istediğiniz her hangi bir lisans ile yayınlayabiliyorsunuz (evet para kazanmak da mümkün). Gücünü <a href="http://www.libsdl.org/">SDL (Simple DirectMedia Layer)</a> denen bir kütüphaneden alıyor. Bahsi geçen SDL, <a href="http://tr.wikipedia.org/wiki/C_%28programlama_dili%29">C</a> ve <a href="http://tr.wikipedia.org/wiki/Assembly">Assembly</a> dili kullanılarak yazılmış bolca optimizasyondan geçmiş, hız konusunda tartışmasız bir biçimde tatmin edici. Anlayacağınız PyGame'in duruşu pek şirin olsa da arkasında bir canavar yatıyor.<br /><br />Aslına bakarsanız bir video kurgu programı yapmak için bile uygun gördüm kendisini, "oyun yapmak için kütüphane" tanımı biraz zayıf kalıyor kendisini anlatmaya.<br /><br />Evet SDL kütüphanesi çok güçlü ama "Python dili oyun programlama yapmak için uygun mu?" sorusunu cevaplamak gerekiyor.<br /><br />Python çok üst seviyeli bir dil, bir C kodundan yaklaşık 20 kat yavaş çalışıyor. Zaten bu programlama dilini tercih ederken pek performansına bakarak karar vermedik hiçbirimiz. Python dilinin asıl vurucu noktası bildiğiniz gibi kolay öğrenilir olması, ve size çok çabuk çözümler sunabilmesi. Python ve PyGame ile oyun yapmaya niyetlendiyseniz, bir "enemy-territory yapayım" şeklinde hayallere dalmanız sizi hayal kırıklığına uğratır. Yapabileceğiniz genelde hafif diye tabir edebileceğimiz oyunlar. Zaten genelde PyGame ile yapılmış oyunları incelediğinizde flash oyunu türevi ya da eski ATARI-C64 oyunlarının yeniden yapılmış halleri ile karşılaşıyoruz.<br /><br />Bunların yanında PyGame hoş bir topluluğa sahip.İnsanları oyun geliştirilmesine teşvik etmek amacıyla "bir hafta içerisinde en güzel oyunu kim geliştirecek?" konseptine sahip bir yarışma düzenliyorlar adı da <span style="text-decoration: underline;"></span><a href="http://www.pyweek.org/">PyWeek</a><a href="http://www.pyweek.org/" pyweek="">.</a> Siteye uğrayıp en azından o hafta yarışmaya katılmış oyunları oylamak bile yeterince eğlenceli bir aksiyon. Gerçekten güzel işler var ve tabi ki hepsinin kodları açık.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com0tag:blogger.com,1999:blog-7247155306507171101.post-1973472738206414412008-11-26T12:51:00.000-08:002008-11-26T13:04:01.869-08:00Nano SnakeCep telefonlarından bildiğimiz yılan oyunu Python ile 13 satırlık bir kod ediyormuş =)<br />Konsolda <a href="http://sudrap.org/paste/5123/duzyazi/">şuradaki</a> komutu verin. Tahmin edebileceğiniz gibi pygame sistemde kurulu olmalı.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com2tag:blogger.com,1999:blog-7247155306507171101.post-12550469576340304402008-11-22T02:53:00.000-08:002008-11-22T02:57:28.819-08:00Kod aramakBen her hangi bir konuda kod örneği bulmak için şu siteleri kullanıyorum, sizin de işinize yarayabilir.<br /><br /><ul><br /><li><a href = "http://www.google.com/codesearch">http://www.google.com/codesearch</a></li><br /><li><a href = "http://github.com/codesearch">http://github.com/codesearch</a></li><br /><li><a href = "http://www.krugle.org/kse/files">http://www.krugle.org/kse/files</a></li><br /><li><a href = "http://www.koders.com/">http://www.koders.com/</a></li><br /></ul><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com1tag:blogger.com,1999:blog-7247155306507171101.post-80228321557623877762008-11-11T11:13:00.000-08:002008-11-11T11:14:07.698-08:00setup.py Dosyası hazırlamak<p>Bu yazımızda python un <b>distutils</b> (<i>distutils.core.setup</i>) modülü ile kurulum betiği hazırlayacağız...</p> <p><b>distutils</b> modülü öntanımlı olarak python ile gelmektedir.</p> <p>Öncelikle setup.py den biraz bahsedeilm: çoğu python uygulaması distutils ile kurulum betikleri hazırlar, bunun nedeni distutils in sorunsuz, kolay ve tabi ki python ile birlikte geliyor olması diyebiliriz. :D</p> <p>Şimdi betiğimizi yazalım:</p> <p><code class="python"><br /># -*- coding: utf-8 -*-<br /># setup.py denemesi...<br /><br />from distutils.core import setup # distutils.core modülündeki setup metodununu çağırıyoruz...<br /><br /># simge gibi şeyleri tanımlıyoruz...<br />datas = [("share/applications", ["data/kxmp.desktop"]), ("share/pixmaps", ["kxmp/kxmp.png"])]<br /><br />setup(name = "kxmp",<br /> version = "0.1.2",<br /> description = "Graphical xm player...",<br /> author = "Oğuzhan Eroğlu",<br /> author_email = "oguzhan@oguzhaneroglu.com",<br /> url = "http://kxmp.googlecode.com",<br /> packages = ["kxmp"],<br /> data_files = datas,<br /> scripts = ["data/kxmp"])<br /></code><br /><br /></p> <p>Şimdi de kodu açıklayalım:<br /><b>setup argumanları:<br /></b></p> <ul><li><b>name:</b> Uygulamanın adı.</li><li><b>version: </b>Uygulamanın sürüm numarası (str olmalı)</li><li><b>description: </b>Uygulamanın ne yaptığını anlatan kısa bir açıklama.</li><li><b>author:</b> Yazarın adı.</li><li><b>author_email:</b> Yazarın e-posta adresi.</li><li><b>url:</b> Uygulamanın proje sayfası.</li><li><b>packages:</b> Uygulamanın kaynak kodlarının bulunduğu yani kurulacak dizinler (liste olmalı)</li><li><b>data_files:</b> Uygulamanın çalıştırma dosyası, .desktop gibi dosyaların bulunduğu dizin. (liste olmalı)</li><li><b>scripts:</b> /usr/bin altına gidecek betikler. (liste olmalı)</li></ul> <p>burdan önemli noktalara değinecek olursak:<b><br />packages</b>, <b>data_files</b>, <b>scripts</b> argumanları liste olmalıdır, çünkü bu tür dizinler birden fazla da olabilir.</p> <p>datas değişkenini açıklayacak olursak:<br />yapılan işlem şu liste içerisine bilgiler ("hedefdizin", [kaynakdizinler]) şeklinde veriliyor.</p> <p>ve dikkat ettiyseniz setup hep /usr/ altında çalışır yani <i>/usr/share/applications</i> yazmak yerine <i>share/applications</i> yazarız.</p> <p>Yaptığı şeye değinecek olursak çok basit kodlarınızı site-packages dizinine atıyor... yani uygulamayı çalıştıracak betik sadece import a dese yeterli (a burada packages argumanına verilen dizinlerden biri).</p> <p>İyi çalışmalar...</p><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Oğuzhan Eroğluhttp://www.blogger.com/profile/09142565628105212005noreply@blogger.com13tag:blogger.com,1999:blog-7247155306507171101.post-77830575888380916842008-11-11T04:03:00.001-08:002008-11-28T06:17:35.362-08:00Python projesinde klasör yapısıBunları yap:<br /><br /><ul><li>Projenizin en üst dizininin adı projenizle aynı olsun, - işareti ile birlikte versiyonu belirtin. Örneğin projenin adı Twisted ise root klasörünüz Twisted-2.5 gibi birşey olabilir.<span style="font-family:monospace;"></span></li><li><span style="font-family:monospace;"></span>Twisted/bin dizinini oluşturun, ve eğer var ise çalıştırılabilir dosyalarınızı buraya koyun. Eğer çalıştırılabilir dosyanız bir python kodu ise soy adından .py ifadesini kaldırın. Bahsi geçen Python kodu dizin yapınız içerisinde başka bir yerde duran main fonksiyonunu çağırmaktan başka bir işe yarıyor olmamalı.</li><li>Projeniz tek bir Python betiğinden oluşuyor ise bunu kök dizininize projenizle aynı ismi vererek yerleştirin. Örneğin: Twisted-2.5/Twisted.py<span style="font-family:monospace;"></span></li><li><span style="font-family:monospace;"></span>Projeniz birden fazla Python kaynak kodundan oluşuyor ise kök dizininiz altında bir paket (python pakedi) oluşturun (Twisted-2.5/twisted klasörü oluşturup içine __init__.py dosyası koyun) ve kodlarınızı buraya yerleştirin. Örneğin Twisted-2.5/twisted/internet.py<span style="font-family:monospace;"></span></li><li>Test araçlarınızı kök dizin içerisinde başka bir paket içerisine koyun (Twisted-2.5/tests/). Örneğin önceki örnekteki Twisted-2.5/twisted/internet.py yi test eden test-internet.py yi buraya koyun.</li><li><span style="font-family:monospace;"></span>Kök dizininize README gibi dosyaları ve setup.py nizi yerleştirin.<br /></li></ul><pre>Bunları yapma:<br /></pre><ul><li>Kodlarını src yada lib gibi klasörlere koyma bu progamı yerleştirmeden (install etmeden) çalıştırılmasını zorlaştırır.<span style="font-family:monospace;"></span></li><li><span style="font-family:monospace;"></span>Pakedin içindeki Python betiklerini test eden python betiklerini pakedin içinden başka bir pakedin içine koymaz iseniz kurulum yapıldıktan sonra testleri yapmak zorlaşacaktır.<span style="font-family:monospace;"></span></li><li>Bir paket oluşturup sadece __init__.py içerisine fonksiyonları dizeceksen bunun yerine bir modül oluşturman çok daha kolay olur.</li></ul>Kaynak : http://jcalderone.livejournal.com/39794.html<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-20263810301922712332008-10-30T04:31:00.000-07:002008-10-30T04:34:16.539-07:00Google App Engine uygulama geliştirme 2Google App Engine ile uygulama geliştirmenin ikinci sayısında aslında sizlere apilerden bahsedecektim ama farklı konulardan bahsedeceğim. Bunlar;<br /><br /> 1. Google App Engine Django Kurulumu<br /> 2. Google App Engine ve Django Form Yaratma<br /> 3. Formları İşleme Ziyaretçi Defteri Uygulaması<br /><br />Hiç laf ebeliği yapmadan olaya giriyorum çünkü uzun bir yazı olacak.<br /><br /><span style="font-weight: bold;">1. Google App Engine Django Kurulumu:</span><br /> Ö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.<br /><br /> 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<br /><br /> b) <a href="http://docs.google.com/Doc?id=ddtkpndp_98fb9qfxhm">main.py</a><br /><br /> c) <a href="http://docs.google.com/Doc?id=ddtkpndp_99n7hhc3cq">settings.py</a><br /><br /> d) app.yaml<br /><code class="python"><br />application: app_engine_domain_adi<br />version: 1<br />runtime: python<br />api_version: 1<br /><br />handlers:<br />- url: /.*<br /> script: main.py<br /></code><br /> 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<br /><br /> e) Artık bir uygulama başlata biliriz ortam uygun hale geldi :D<br /> > cd yetis<br /> > python manage.py startapp Blog <br />uygulamamızın adı Blog olsun...<br /><br />Artık Django'yu Google App Engine'de kullanabilirsiniz.<br /><br /><span style="font-weight:bold;">2. Google App Engine ve Django Form Yaratma ve İşleme:</span><br /> 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<br /><br />Karışıklığı önlemek için dosya yapısının tree'sini veriyorum.<br />|----- app.yaml<br />|----- index.yaml<br />|----- main.py<br />`----- yetis<br />------|----- Blog<br />------|----|----- bform.py<br />------|----|----- models.py<br />------|----|----- templates<br />------|--------------- ziyaretci.html<br />------|--------- views.py<br />------|----- manage.py<br />------|----- settings.py<br />------------ urls.py<br /><br />Django ile proje başlattık ( yetis ) ve birde uygulama açtık ( Blog ) . Şimdi sıra ile gidelim<br /> a) Model oluşturulacak<br /> b) Model için Form oluşturulacak<br /><br /> a) Model Oluşturulacak:<br /> Modelimizi bir ziyaretçi defteri oluşturma uygulamasına göre oluşturuyorum. <br /><code class="python"><br />from google.appengine.ext import db<br />class Z_Defteri(db.Model):<br /> ad = db.StringProperty(verbose_name="Ad",required=True)<br /> soyad = db.StringProperty(verbose_name="Soyad",required=True)<br /> not_ = db.TextProperty(verbose_name="Mesaj")<br /> inci = db.IntegerProperty(default = 0)<br /> tarih = db.DateTimeProperty(auto_now_add = 1)<br /> yazan = db.UserProperty()<br /><br /> def __unicode__(self):<br /> return "%s %s %s %s"%(self.not_,self.ad,self.soyad,self.inci)<br /></code><br />Modeldeki alanların parantezleri içindeki değişkenlerden bahsedelim. <br /> verbose_name = "Ad" ----> Tablom oluştuğunda alanın ismini "Ad" yaptım. Yani şurası; <input type="text" name="ad" id="id_ad"<br />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<br /> 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 :) <br /> default = 0 ---> Ön tanımlı olarak sıfır değerini alsın.<br /> auto_now_add = 1 ---> Tarihi commit yaptığımda otomatik oluştur.<br /><br /><br /> b) Model için Form oluşturulacak:<br />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 <span style="font-weight:bold;">bform.py</span> adında bir dosya oluşturalım. Dosyanın nerede oluştuğunu yukardaki tree'e bakarak görebilirsiniz.<br />bform.py<br /><code class="python"><br />from models import Z_Defteri<br />from google.appengine.ext.db import djangoforms<br /><br />class ZD_Form(djangoforms.ModelForm):<br /> class Meta:<br /> model = Z_Defteri<br /> fields = ('ad','soyad','not_','tarih',)<br /> exclude = ['inci','yazan']<br /></code><br />----> "from models import Z_Defteri" ile modelimizin aldık<br />----> "from google.appengine.ext.db import djangoforms" Appengine'nin django'da bulunan ModelForm olayını kullanmamızı sağlayan modulunu aldık.<br />----> 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<br />Öntanımlı değişkenlerden bahsedeyim.<br />-----> model = Z_Defteri burada modelimizdeki değişkenleri atadık<br />-----> fields = ('ad','soyad','not_','tarih',) kullanacağımız alanlar<br />-----> exclude = ['inci','yazan'] ilk form oluştuğunda form'da gözükmesini istemediğimiz alanlar.<br /><br />bform.py dosyasının içine bu uygulamada kullanacağınız butun formları atabilirsiniz. Böylelikle herşey toparlı olmuş olur.<br /><span style="font-weight:bold;">3. Formları İşleme Ziyaretçi Defteri Uygulaması</span><br /> İ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!<br /><br />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. <br />Öncelikle views.py dosyası:<br /><code class="python"><br />from django.http import HttpResponse, HttpResponseRedirect<br />from yetis.Blog.models import Z_Defteri<br />from bform import ZD_Form<br />from django.shortcuts import render_to_response<br />from google.appengine.ext import db<br />from google.appengine.api import users<br /></code><br />Formları oluşturduğumuz yer bform.py den ZD_Form'u çektik, users,db apilerini ekledik, djangonun bir kaç fonksiyonunu ekledik.<br /><code class="python"><br />def ziyaretci_defteri(request):<br /> yazilanlar = Z_Defteri.all()<br /> yazilanlar.order("-tarih")<br /> yazilanlar = yazilanlar.fetch(10)<br /> <br /> kullanici = users.get_current_user()<br /> ndform=''<br /> if kullanici:<br /> k_islem = ("Hosgeldiniz, %s! (<a href=\"%s\">Cikis Yap</a>)" %(kullanici.nickname(), users.create_logout_url("/")))<br /> <br /> if request.method == "POST":<br /> zdform = ZD_Form(request.POST)<br /> if ndform.is_valid():<br /> yazan = kullanici<br /> inc =Z_Defteri.all()<br /> inci = inc.count()<br /> not_ = (request.POST["not_"]).decode("utf8")<br /> ad = (request.POST["ad"]).decode("utf8")<br /> soyad = (request.POST["soyad"]).decode("utf8")<br /> kayit = Z_Defteri(not_=not_,ad=ad,soyad=soyad,inci=inci,yazan=yazan)<br /> kayit.put()<br /> return HttpResponseRedirect('/')<br /> else:<br /> zdform = ZD_Form()<br /><br /> else:<br /> k_islem = ("<a href=\"%s\">Giris Yapiniz</a>." % users.create_login_url("/"))<br /> <br /> return render_to_response('ziyaretci.html',{'zdform':zdform,'yazilanlar':yazilanlar,'k_islem':k_islem,'kullanici':kullanici} )<br /></code><br />Algoritması! <br />--->Önce sayfaya giren kişinin google kullanıcısı olup olmadığına bakıyoruz,<br />-------> google kullanıcısı ise ziyaretçi defterine not bırakmasına izin veriyoruz <br />-------------> Eğer Post ediliyor ve mothodumuz POST ise Form oluştur<br />-------------------->submit tuşuna basılmış ve Form boş bırakılmamışsa<br />-------------------------->Veritabanına Formda girilen alanları yaz.<br />-------------> Post edilmemiş ise sadece Form oluştur<br />--->değil ise google giriş sayfasına yönlendiriyoruz giriş yapıp tekrar yönlendirilsin.<br />Değişkenleri anlatacağım;<br />yazilanlar --> Ziyaretçi defterine yazılan yazının argümanlarının tamamını sorgu ile çekiyor.<br />kullanici --> Sayfayı ziyaret eden kişi. Dilerse deftere birşeyler yazabilir.<br />k_islem --> kullanici işemleri. Giriş ve Çıkış işlemi sadece :D<br />zdform --> Ziyaretçi Defteri form bilgilerini bu değişken ile alıyoruz. Form bu değişkende oluşuyor.<br /><br />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.<br />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.<br />en üstte {{k_islem}} koyarak kullanıcının gmail kullanıcı olup olmadığına bakarak yönlendirebiliriz.<br /><code class="python"><br /> <form action="." method="post"><br /> <table><br /> {{zdform}}<br /> </table><br /> <table><br /> <input type="submit" name="gonder" value="Gönder" class="inputsag"/><br /> </table><br /> </form><br /></code><br />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. <br /><br /><code class="python"><br /> {% for not in yazilanlar %}<br /> <table><br /> <TD><br /> <p id="kisi">{{not.ad}} {{not.soyad}} <hr><br /> <em> id="eposta">{{not.yazan.email}}</em><br /> <em id="tarih">{{not.tarih|date:"d M Y D"}}</em></p><br /> <p> id="mesaj">{{not.not_}}</p><br /> </table><br /> </TD><br /> {% endfor %}<br /></code><br />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. <br />html dosyasının kod kısmı buradan ibarettir.<br /><br />Çalışır halini görmek için <h2><span style="font-weight:bold;"><a href="http://pythonizm.appspot.com">http://pythonizm.appspot.com</a></span></h2><br /><br />referanslar:<br />1- http://code.google.com/appengine/docs/datastore/creatinggettinganddeletingdata.html<br />2- http://appengineguy.com/2008/06/proper-unit-testing-of-app-enginedjango.html<br />3- http://www.djangobook.com/en/1.0/chapter07/<br />4- http://docs.djangoproject.com/en/dev/ref/forms/fields/<br />5- http://code.google.com/appengine/articles/django.html<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Yetişhttp://www.blogger.com/profile/03568362306405214586noreply@blogger.com1tag:blogger.com,1999:blog-7247155306507171101.post-84931999833967834632008-10-21T05:15:00.000-07:002008-10-21T05:24:08.473-07:00Djangoya 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.<br /><br />1) <a href="http://docs.djangoproject.com/en/dev/intro/#intro-index">Buradan </a> 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.<br /><br />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 <a href="http://docs.djangoproject.com/en/dev/topics/#topics-index">buradan </a> faydalanabilirsiniz.<br /><br />3) <a href="http://docs.djangoproject.com/en/dev/howto/#howto-index">How-to </a>lardan inceleyebilirsiniz.<br /><br />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 <a href="http://docs.djangoproject.com/en/dev/ref/#ref-index"> burayı </a> ziyaret edebilirsiniz.<br /><br />5) Yeni sürümlerle gelen özellikleri ve değişiklikleri takip etmek için <a href="http://docs.djangoproject.com/en/dev/releases/#releases-index"> burayı </a> Herşeyi aştım birazda katkıda bulanayım diyorsanız da <a href="http://docs.djangoproject.com/en/dev/internals/#internals-index"> burayı </a> ziyaret edebilirsiniz.<br /><br />Sizin de eklemek istedikleriniz olursa tecrübelerinizi ve önerilerinizi yorumlar kısmında paylaşmanızdan memnuniyet duyacağız ;)<br /><br />Bunlar yanında bizi izlemeye devam edebilirsiniz :)<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Deniz Silahcılarhttp://www.blogger.com/profile/10281745069741792531noreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-48801351324434603232008-10-20T12:46:00.000-07:002008-10-20T12:57:12.374-07:00İlişkisel Alanlar (Relationship Fields)<span style="font-weight: bold;">ForeignKey</span><br />Aşağıda foreingkey'in kullanımını anlatmak amacıyla yazılmış ufak bir örnek göreceksiniz.<br /><code class="python"><br />from django.db import models<br /><br />class Yazar(models.Model):<br /> isim = models.CharField(max_length=30) #[1]<br /><br />class Makale(models.Model):<br /> baslik = models.CharField(max_length=100) #[2]<br /> yazar = models.ForeignKey(Yazar) #[3]<br /></code><br /><br />[1] Yazar tablosunda CharField veri türünde bir alan oluşturuyoruz.<br />[2] Makale tablosunda CharField veri türünde bir alan oluşturuyoruz.<br />[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.<br /><br /><code><br />Yazar <br />id--|--isim--|<br />1 --|Mirat---|<br />2 --|Gokmen--|<br />3 --|Deniz---|<br /><br />Makale<br />id--|--baslik--|--yazar_id--|<br />1---|Django----|-----1------|<br />2---|Python----|-----1------|<br />3---|PyQt------|-----3------|<br /></code><br />Id ile gösterilene alanlar tablomuzun PrimaryKeyleri. Biz eklememiş olmamıza rağmen django otomatik olarak bir PrimaryKey alanı oluşturuyor.<br />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 ;) )<br /><br />Şimdi djangoyu ilgilendiren kısımlarına gelelim.<br /><br />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)<br /><code class="python"><br /><br />class ornek(models.Model)<br /> yazar = model.ForeignKey('uygulama.tabloadi')<br /></code><br /><br />ManyToManyField<br />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.<br /><br /><code class="python"><br />from django.db import models<br /><br />class Yazar(models.Model):<br /> isim = models.CharField(max_length=30)<br /><br />class Kitap(models.Model):<br /> baslik = models.CharField(max_length=100)<br /> yazar = models.ManyToMany(Yazar)<br /></code><br /><br />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.<br /><code><br />Yazar <br />id--|--isim--|<br />1 --|Mirat---|<br />2 --|Gokmen--|<br />3 --|Deniz---|<br /><br />Kitap<br />id--|--baslik--|<br />1---|Django----|<br />2---|Python----|<br />3---|PyQt------|<br /><br />yazarkitap<br />id--|--yazar_id--|--kitap_id--|<br />1---|----1------|-----1------|<br />2---|----1------|-----2------|<br />3---|----2------|-----3------|<br />4---|----3------|-----1------|<br /></code><br />Ş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)<br />yazar tablosundan da o id'ye karşılık gelen değerleri öğreniyoruz.(Mirat ve Deniz).<br /><br />İş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"<br /><br />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.<br /><br />Kaynaklar: http://docs.djangoproject.com/en/dev/ref/models/fields/<br />http://www.djangoproject.com/documentation/models/<br />http://docs.djangoproject.com/en/dev/topics/db/models/<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Deniz Silahcılarhttp://www.blogger.com/profile/10281745069741792531noreply@blogger.com3tag:blogger.com,1999:blog-7247155306507171101.post-63628622283538066122008-10-14T04:50:00.000-07:002008-10-14T05:15:10.504-07:00Django model veri tipleriBir veri tipi belirlerken dikkat etmeniz gereken 2 şey vardır:<br /><ol><li>Field ismini rezerve edilmiş python kelimesi olamaz.</li><li>Field ismi birden fazla alt çizgi ("_") işareti barındıramaz.</li></ol>Field sınıfları 3 şeyi ifade etmek için kullanılır.<br /><ul><li>Database sütün tipi (örn: INTEGER, VARCHAR, INT...)</li><li>Django yönetici panelinin kullandığı her hangi bir widget (örn: <input type="text"> )</li><li>Django yönetici panelinin minimal doğruluk gereklilikleri.</li></ul>Şimdi bu alan tiplerine değinelim.<br /><br /><h3>AutoField</h3><br />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)<br /><br /><h3>BooleanField</h3><br />Doğru/Yanlış (True/False) bilgisi tutar.<br /><br /><h3>CharField</h3><br />Karakter katarı tutar çok uzun bir metin tutulacaksa bunun yerine TextField kullanılmalıdır.<br /><br />Charfield fazladan bir parametreye ihtiyaç duyar : maxlength, bu alanınızın en fazla kaç karakterlik veriyi tutabileceğini ifade eder.<br /><br /><h3>CommaSeparatedIntegerField</h3><br />Virgülle ayrılmış sayıların tutulduğu bir alandır. Charfield gibi maxlength argümanına ihtiyaç duyar.<br /><br /><h3>DateField</h3><br />Tarih tutmak için kullanılan bir alandır. İki adet seçimlik argümanı vardır. Bunlar :<br /><dl><dt>auto_now</dt><dd>Otomatik olarak kayıt edilme tarihini tutar. save() komutunu verdiğinizde tarih ne ise alanınız o tarih ile otomatik olarak kaydedilecektir.</dd><br /><dt>auto_now_add</dt><dd>Otomatik olarak nesnenin ilk yaratıldığı tarihi tutar.</dd></dl><br /><br /><h3>DateTimeField:</h3><br />Tarih ve saat bilgisini tutar. DateField la aynı seçimlik argümanları kullanır.<br /><br /><h3>EmailField</h3><br /> 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.<br /><br /><h3>FileField</h3><br />Bir dosya upload alanıdır. Sadece bir gerekli argümana sahiptir.<br /><dl><dt>upload_to:</dt><dd>Yerel dosya sistemi yolu olup config dosyanızdaki MEDIA_ROOT yolu ile birleştirilip kullanılacaktır.</dd></dl><br /><br />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)<br /><br /><h4>FileField ve ImageField alanlarını kullanmak için</h4><br /><ol><li>Ayarlar dosyanızda MEDOA_ROOT dizini Django'nun upload edilen dosyaları nereye koyacağını belirler. Buraya tam yolu yazın.</li><li>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.</li><li>Dosyanız kayıt edilden sonra Django size get_<dosyadi>_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.</dosyadi></li></ol><br /> <br />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.<br /><br /><h3>FilePathField</h3><br />Seçimleri dosya sistemiz üzerindeki dosyalarla sınırlı olan bir alandır. Üç özel argümana sahiptir.<br /><dl><dt>path</dt><dd>Gerekli, sistemdeki her hangi bir klasörü gösteren tam yol.</dd><br /><dt>match</dt><dd>Seçimlik, bahsi geçen klasör içerisinde hangi dosyaları seçeceğini gösteren düzenli ifade.</dd><br /><dt>recursive:</dt><br /><dd>Seçimlik, True ise match ifadesi alt dizinlerde de aranır. False olarak öntanımlanmıştır.</dd></dl><br /> <br /><b>Örnek:</b> FilePathField(path="/home/texts", match="*.txt", recursive=True)<br /> <br /><h3>FloatField</h3><br />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.<br /><dl><dt>max_digits</dt><dd>Sayının en fazla sahip olabileceği basamak sayısı.</dd><br /><dt>decimal_places</dt><dd>Sayının ondalıklı kısmının kaç basamaklı olacağını belirler.</dd></dl><br /><br /><h3>ImageField</h3><br />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.<br /><br /><h3>IntegerField</h3><br />Tamsayı tutar.<br /><br /><h3>IpAdressField</h3><br />Bir ip adresini karakter katarı olarak tutar (örn: "127.0.0.1")<br /><br /><h3>NullBooleanField</h3><br />BooleanField gibir fakat bunun yanına bir adet de None değeri eklenmiştir. True/False/None değerlerini tutabilir.<br /><br /><h3>PhoneNumberField</h3><br />Özelleştirilmiş bir CharField tipidir fakat ek olarak girilen metnin U.S. tipi telefon numarası biçimlemesine uyup uymadığına bakar (XXX-XXX-XXXX)<br /><br /><b>Not:</b> Başka bir ülkenin telefon numarasını kontrol etmek isterseniz django.contrib.localflavor pakedine bir göz atın.<br /><br /><h3>PositiveIntegerField</h3><br />IntegerField ile aynıdır fakat sadece pozitif tamsayıları tutar.<br /><br /><h3>PositiveSmallIntegerField</h3><br />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.<br /><br /><h3>SlugField</h3><br />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.)<br /><br />CharField da olduğu gibi maxlength parametresi alabilir eğer almadıysa öntanımlı maxlenth parametresi 50 karakterdir.<br /><br />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.<br /><br /><h3>SmallIntegerField</h3><br />PositiveSmallIntegerField'ın aynısıdır fakat buradaki sayı işaretlidir. Genellikle -32,768 ile +32,767 arasındaki sayıları ifade edebilir.<br /><br /><h3>TextField</h3><br />Sınırsız metin alanıdır.<br /><br /><h3>TimeField</h3><br />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.<br /><br /><h3>UrlField</h3><br />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).<br /><br /><h3>XmlField</h3><br />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.<div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Mirat Can Bayrakhttp://www.blogger.com/profile/17818480499669475240noreply@blogger.com0tag:blogger.com,1999:blog-7247155306507171101.post-76892780633451947152008-10-11T11:50:00.001-07:002008-10-11T11:50:48.410-07:00Google App Engine uygulama geliştirme 1Son 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.<br /><br /><ul><li>500 mb web alanı,</li><br /><li>9 tane app engine uygulaması açabilirsiniz ki bu toplamda 4500 mb'lık web alanı demek,</li><br /><li>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.</li><br /><li>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</li><br /><li>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.<br /></li><br /><li>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.</li><br /><li>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ı.</li><br /></ul><br />*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.<br /><code class="python"><br />application: gencistatistik<br />version: 2<br />runtime: python<br />api_version: 1<br /></code><br /><ul><br /><li>application kısmı uygulamamızın AppEngine'deki adını yazılıyor</li><br /><li>runtime kısmı uygulamanın hangi dili kullandığını</li><br /><li>api_version api versionudur. Bu kısmı pek anlamış değilim</li><br /><li>version bu kısımda projenizi versionlara ayırabilirsiniz.</li><br />Ö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<br /><br /><br /> İş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. ( <a href="http://www.pytr.org/portal/content/google-app-engine-ile-web-uygulamalar%C4%B1-geli%C5%9Ftirme-1">TIKLA</a> )<br /><br /> 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.<br />Dosyanın içerik listesi. <br />mysite<br />------><span style="font-weight:bold;">static</span><br />------><span style="font-weight:bold;">python</span><br />--------------><span style="font-weight:bold;">templates</span><br />---------------------------->blogyaz.html<br />---------------------------->index.html<br />-------------->hello.py<br />------>app.yaml<br />Python dosyası sadece bir tane var. Bütün python kodları aynı yerde, parçalamadım.<br /><code class="python"><br />from google.appengine.ext import webapp<br />from google.appengine.ext.webapp.util import run_wsgi_app<br />from google.appengine.api import users<br />from google.appengine.ext import db<br />from google.appengine.ext.webapp import template<br />#Blog uygulamamda kullanmak için tablolarım.<br />class Blogum(db.Model):<br /> yazan = db.UserProperty()<br /> girdi = db.TextProperty()<br /> blogbaslik = db.StringProperty()<br /> date = db.DateTimeProperty(auto_now_add=True)<br /><br />class Karsilama(db.Model):<br /> yazan = db.UserProperty()<br /> yazi = db.StringProperty(multiline=True)<br /> date = db.DateTimeProperty(auto_now_add=True)<br /></code><br />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<br /><code class="python"><br />class AnaSayfa(webapp.RequestHandler):<br /> def get(self):<br /> bloglar = Blogum.all()<br /> bloglar.order("-date")<br /> kullanici = users.get_current_user()<br /> if kullanici:<br /> url = users.create_logout_url(self.request.uri)<br /> url_linktext = "Çıkış"<br /> else:<br /> url = users.create_login_url(self.request.uri)<br /> url_linktext = "Giriş"<br /> template_values = {<br /> "bloglar":bloglar,<br /> "url":url,<br /> "url_linktext":url_linktext,<br /> "kullanici":kullanici}<br /> path = os.path.join(os.path.dirname(__file__), 'templates/index.html')<br /> self.response.out.write(template.render(path, template_values))<br /></code><br />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 <a href="http://code.google.com/appengine/docs/datastore/">TIKLA</a> burayı biraz kurcalayın.<br />kullanici = users.get_current_user() burada Appenginenin <a href="http://code.google.com/appengine/docs/users/">Users Api</a>'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.<br /><br />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.<br /></ul><div class="blogger-post-footer">Bir gurup Python programcısının karşılaştığı komik veya önemli sorunlar, çözümleri ve kazandıkları tecrübeler üzerine aldıkları notlardan oluşan bir "web" günlüğüdür.</div>Yetişhttp://www.blogger.com/profile/03568362306405214586noreply@blogger.com1