31 Mart 2014 Pazartesi

Python QT (PyQt) Kurulumu


PyQT, Riverbank tarafından geliştirilmektedir.
Linux dağıtımlarında genellikle PyQt paketi bulunmaktadır. Ancak yok ise Terminale
  • sudo apt-get install python2-pyqt4
kodunu yazdığınızda Python 2.x sürümü için PyQt4 paketini yükleyebilirsiniz.

Windows kullanıcıları ise http://www.riverbankcomputing.co.uk/software/pyqt/download adresine gidip kullandıkları sisteme ve Python sürümüne uygun PyQt paketini indirmelidirler.
Burada PyQt paketi dağıtımlarının isimlerinde Python sürümü, lisans türü ve Qt sürümü yazmaktadır. Biz sizler için burada Python 2.x için Qt4.8.5 sürümünün kurulumunu göstereceğiz.

Öncelikle Riverbank'ın sitesinden gerekli indirme işlemini yapıyoruz ve sonrasında inen kurulum dosyasını çalıştırıyoruz. Sırayla gelen ekranda Next ondan sonra gelen lisans sözleşmesi ekranında I Agree deyin.




Daha sonra karşınıza yüklemek istediğiniz bileşenleri soran yandaki ekran gelecektir. Burada bir değişiklik yapmanızı önermiyorum. Bu şekilde kuruluma Next diyerek devam edin.






Daha sonra karşınıza yandaki ekran gelecek burada PyQt'nin nereye kurulacağı sorulmaktadır. Kurulum asistanı Python2.7'nin nerede olduğunu bulamamışsa, Python 2.7'nin kurulu olduğu klasörü belirtin. Sonrasında da Install diyerek kurulumu gerçekleştirin.


Kurulum tamamlandıktan sonra gelen ekranda ise Finish diyerek, PyQt paketinin kurulumunu bitiriyoruz.


Kurulumu tamamladığınızdan emin olmak için kontrol edebilirsiniz. Bunun için Python'un etkileşimli kabuğuna
import PyQt4
yazmanız yeterli. Eğer
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import PyQt4
ImportError: No module named PyQt4
hatası alıyorsanız, kurulum hatalıdır. Hata almadan bir alt satıra geçmiş iseniz kurulumu doğru bir şekilde tamamlamışsınızdır.

Kaynaklar:
http://www.istihza.com/beta/qt4/temel_bilgiler.html
Mustafa Başer - Python Kitabı

28 Mart 2014 Cuma

Formlar

Şimdi formları daha detaylı kullanarak daha önceki hastahane projesinde kullanıcıya yeni Doktor ekleme işlemi yaptıralım. İlk önce formu barındıran bir şablon oluşturalım.
<!DOCTYPE html>
<html>
<head>
    <title>Doktor Ekleme</title>
    <link rel="stylesheet" type="text/css" href="/dosyalar/base.css" />
</head>
<body>

<h1>Doktor Ekle</h1>

<form action="/doktor-ekle/" method="post">
    {% csrf_token %}
    <table>
        <tr><th>Adı:</th><td><input type="text" name="adi"/></td></tr>
        <tr><th>Soyadı:</th><td><input type="text" name="soyadi"/></td></tr>
        <tr><th>Telefon</th><td><input type="text" name="telefon"/></td></tr>
        <tr><th>E-Posta</th><td><input type="text" name="eposta"/></td></tr>
         <tr><th></th><td><input type="submit" value="Ekle"/></td></tr>
    </table>

</form>

</body>
</html>
Buradaki kullandığımı % csrf_token %} satırına dikkat etmişsinizdir. Bu değişken Cross Site Request Forgery saldırılarından korunmak için form içerisinde her oturum için rastgele bir değer üretilip bu değer kullanıcıdan geleni ile karşılaştırıldıktan sonra işlemin yapılmasını sağlar. Form kaynağına bakarsanız şu şekilde bir satır görürebilirsiniz:
<input type='hidden' name='csrfmiddlewaretoken' value='yrseedSoajFQTxom0vYD8hD6QAj8CPo8' />
Şimdi kullanıcıdan verileri alarak ekrana yazdıran görünümü oluşturalım.
from django.http import *
from django.template import RequestContext
def doktor_ekle(request):
 if request.method == "POST":
  adi = request.POST.get('adi')
  soyadi = request.POST.get('soyadi')
  telefon = request.POST.get('telefon')
  eposta = request.POST.get('eposta')
  return HttpResponse('''
  <strong>Adi:</strong> %s <br/>
  <strong>Soyadi:</strong> %s <br/>
  <strong>Telefon:</strong> %s <br/>
  <strong>E-Posta:</strong> %s <br/>
  '''%(adi,soyadi,telefon,eposta))
 else:
  return render_to_response('doktor_formu.html',context_instance = RequestContext(request) )
Görünümü de oluşturduk. Tabi kullanıcının form'a ulaşabilmesi için urls.py dosyasına şu satırı eklememiz gerekiyor.
url(r'^doktor-ekle/',yonetim.views.doktor_ekle),
Artık tarayıcıdan localhost:8000/doktor-ekle diyerek forma ulaşabiliriz. Formu post ederek sonuçlarına bakabilirsiniz. Tabi biz burada sadece ekrana yazdırdık. Burada yapmamız gereken aldığımız verileri veritabanına eklememiz gerekir. Ama biz verileri alırken hiç bir filtreleme işlemi yapmadık. Hatırlarsanız Doktor tablosunda ad ve soyad kısımları zorunlu alanlardı. Eğer biz kullanıcı POST ettiğinde bu alanların dolu olup olmadığını kontrol etmezsek veritabanına eklemeye çalışırken Django hata döndürür. Bu yüzden ilk önce aldığımız verilerin kontrolünü yapalım. Görünümü şu şekilde değiştiriyoruz.
def doktor_ekle(request):
 if request.method == "POST":

  adi = request.POST.get('adi')
  soyadi = request.POST.get('soyadi')
  telefon = request.POST.get('telefon')
  eposta = request.POST.get('eposta')

  hatalar = []
  if not (adi or soyadi):
   hatalar.append('Adı veya soyadı boş bırakılamaz.')
  if eposta:
   if not ('@' and '.') in eposta:
    hatalar.append('Doğru bir E-posta adresi girmelisiniz.')
  if telefon:
   if len(telefon) != 11:
    hatalar.append('Telefon numarası 11 haneli olmalı.')
  if hatalar:
   return HttpResponse('Hataları düzeltip tekrar gönderin: <li>%s' % ' <li>'.join(hatalar))
  return HttpResponse('''
  <strong>Adi:</strong> %s <br/>
  <strong>Soyadi:</strong> %s <br/>
  <strong>Telefon:</strong> %s <br/>
  <strong>E-Posta:</strong> %s <br/>
  '''%(adi,soyadi,telefon,eposta))
 else:
  return render_to_response('doktor_formu.html',context_instance = RequestContext(request) )
Burada eğer adı veya soyadı girilmediyse, kullanıcı telefon numarasını eksik veya fazla girdiyse, eposta adresi içerisinde @ ve . işaretleri yoksa kullanıcıya hata döndürüyoruz. Kullanıcı hatalı girdiği zaman geri dönerek tekrar düzeltmek zorundadır. Biz bu şekilde yapmayalım da kullanıcı hatalı girerse hataları ve formu aynı sayfada göstererek kullanıcıyı uyaralım. Görünümü tekrardan şu hale getirelim.
def doktor_ekle(request):
 if request.method == "POST":

  adi = request.POST.get('adi')
  soyadi = request.POST.get('soyadi')
  telefon = request.POST.get('telefon')
  eposta = request.POST.get('eposta')

  hatalar = []
  if not (adi and soyadi):
   hatalar.append('Adı veya soyadı boş bırakılamaz.')
  if eposta:
   if not ('@' and '.') in eposta:
    hatalar.append('Doğru bir E-posta adresi girmelisiniz.')
  if telefon:
   if len(telefon) != 11:
    hatalar.append('Telefon numarası 11 haneli olmalı.')
  if hatalar:
   return render_to_response('doktor_formu.html',locals(),context_instance = RequestContext(request))
  else:
   return HttpResponse('''
   Adi: %s 
Soyadi: %s
Telefon: %s
E-Posta: %s
'''%(adi,soyadi,telefon,eposta)) else: return render_to_response('doktor_formu.html',context_instance = RequestContext(request))
Eğer hata ile karşılaşırsa tekrardan doktor_formu.html şablonuna yönlendireceğiz. Bu sayfaya yönlendirdiğimiz zaman formdaki alanlar boş gelecektir. Bunu engellemek için doktor_formu.html şablonunda POST ile gelen verileri elemanlar içerisine yazdırmamız gerekli. Hataları da yine aynı şekilde şablon içerisinde yapacağız. Bu yüzden doktor_formu.html şablonu üzerinde bazı değişiklikler yapacağız.
Uyarı: Eğer bir Python dosyasında Türkçe karakter kullanırsanız hata ile karşılaşırsınız. Hata ile karşılaşmamak için dosya içerisinde en başa şu kodu yazmanız gerekir.
# -*- coding: utf-8 -*-
Bizim dosyalarımızda bu kod olduğu için Türkçe karakterlerde herhangi bir sıkıntı yaşanmadı.
<!DOCTYPE html>
<html>
<head>
    <title>Doktor Ekleme</title>
    <link rel="stylesheet" type="text/css" href="/dosyalar/base.css" />
</head>
<body>

<h1>Doktor Ekle</h1>

{% if hatalar %}
    <span style="color:red">
        {{ hatalar|unordered_list }}
    </span>
{% endif %}

<form action="/doktor-ekle/" method="post">
    {% csrf_token %}
    <table>
        <tr><th>Adı:</th><td><input type="text" name="adi" value="{{ adi }}"/></td></tr>
        <tr><th>Soyadı:</th><td><input type="text" name="soyadi" value="{{ soyadi }}"/></td></tr>
        <tr><th>Telefon</th><td><input type="text" name="telefon" value="{{ telefon }}"/></td></tr>
        <tr><th>E-Posta</th><td><input type="text" name="eposta" value="{{ eposta }}" /></td></tr>
         <tr><th></th><td><input type="submit" value="Ekle"/></td></tr>
    </table>

</form>

</body>
</html>
Burada kullanıcı hatalı giriş yaparsa şu şekilde bir çıktı ile karşılaşacaktır. Bir kaç deneme yapabilirsiniz.
Şimdi gelelim asıl işlemimize. Kullanıcıdan verileri aldıktan sonra ne yapacağız ? Tabi ki veritabanına eklememiz gerekiyor. Bu yüzden görünümü veritabanına ekleme işlemini yapacak şekilde değiştirmemiz gerekiyor.
def doktor_ekle(request):
 if request.method == "POST":

  adi = request.POST.get('adi')
  soyadi = request.POST.get('soyadi')
  telefon = request.POST.get('telefon')
  eposta = request.POST.get('eposta')

  hatalar = []
  if not (adi and soyadi):
   hatalar.append('Adı veya soyadı boş bırakılamaz.')
  if eposta:
   if not ('@' and '.') in eposta:
    hatalar.append('Doğru bir E-posta adresi girmelisiniz.')
  if telefon:
   if len(telefon) != 11:
    hatalar.append('Telefon numarası 11 haneli olmalı.')
  if hatalar:
   return render_to_response('doktor_formu.html',locals(),context_instance = RequestContext(request))
  else:
   doktor = Doktor(adi=adi,
       soyadi=soyadi,
       telefon=telefon,
       eposta=eposta)

   doktor.save()
   return HttpResponseRedirect('/doktorlar/')
 else:
  return render_to_response('doktor_formu.html',context_instance = RequestContext(request))
Doktor ekleme işlemi yaptıktan sonra daha önceden hazırlamış olduğumuz veritabanında ki doktorları listeleyen doktorlar sayfasına yönlendirme yapıyoruz.
Eğer isterseniz formları kullanmak için şu yolu da kullanabilirsiniz. Formu çağırdığınız ve post edildikten sonra işlemleri yapacağınız görünümü birbirinden ayırabilirsiniz.
## urls.py
 url(r'^arama/',yonetim.views.arama),
 (r'^arama-form/',yonetim.views.arama_form),
## views.py
def arama_form(request):
 return render_to_response('arama.html',context_instance = RequestContext(request))

def arama(request):
 if request.method == "POST":
  aranan = request.POST.get('aranan')
  return HttpResponse('Aranan ifade : %s' %(aranan))
 else:
  return HttpResponse('Bu şekilde arama yapılamaz..')
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>

<form action="/arama/" method="post">
    {% csrf_token %}
<b>Ara:</b><input type="text" name="aranan" /><br/>
    <input type="submit" value="Ara" />
</form>

</body>
</html>

Kaynakça

25 Mart 2014 Salı

PyQt'ye Giris

pythondersleri.com yeni bir yazı dizisi "PyQt : Grafiksel Kullanıcı Arayüzü Uygulamaları" ile karşınızda! Bu yazıyı okuyarak, PyQt ile haşır neşir olmaya başlamadan önce yazı dizisinin kapsamı ile ilgili olarak fikir sahibi olabilirsiniz.

PyQt, kullanıcılara grafiksel arayüz (GUI) deneyimi sunmak için geliştirilmiş bir Python kütüphanesidir.

Tasarlamış  olduğunuz uygulamaları sunma biçiminiz tamamen sizin tasarrufunuzda olan bir durumdur. Geliştirilmekte olan işletim sistemleri (mobil dahil), kullanıcıların uygulamalar ile olan etkileşimini her geçen gün daha da kolaylaştırmaya çabası içerisindedirler. Dolayısıyla geliştireceğiniz uygulamaların komut satırı arayüzü üzerinde çalışmasından çok, görsel bir arayüz üzerinde çalışması uygulamalarınızın kullanılabilirliğini arttıracaktır.

Python üzerinde GUI uygulamaları geliştirmenizi sağlayacak çeşitli kütüphaneler mevcuttur. Tkinter, PyGObject + GTK3, PyQt bu kütüphanelere örnek olarak gösterilebilirler. PyQt'nin ne olduğunu irdelemeye başlamadan önce Qt ile ilgili bir özet geçmek faydalı olacaktır.
Qt çapraz platform desteği olan GUI geliştirme araç takımıdır. Qt ilk olarak Norveçli Trolltech firması tarafından geliştirilmeye başlanmış, daha sonra Nokia'nın bünyesine katılmıştır. Son olarak başarılı bir özgür yazılım projesi olacağı öngörüsüyle Digia isimli firma tarafından satın alınan Qt, LGPL ile lisanslanarak geliştiricilerin kullanımına sunulmuştur.Yayınlanan en son stabil sürümü 5.2'dir. Dünya çapında büyük firmaların (Google, Adobe, Siemens vb.) Qt altyapısı kullanılarak geliştirilmiş uygulamaları mevcuttur.


PyQt ise Riverbank Computing LTD şirketi tarafından geliştirilmeye devam edilen bir kütüphanedir. Uygulamalarınızda PyQt kullanmayı tercih ederseniz;  2D / 3D grafik desteğinden tutun, Model/View mimarisine kadar birçok yapıyla çalışma imkanına sahip olursunuz. Kısacası modern bir arayüz geliştirme kütüphanesi avuçlarınızın arasında!
Haydi bir sonraki yazıya gözatıp PyQt'ye merhaba deyin!

24 Mart 2014 Pazartesi

GET ve POST Metodları

Kullanıcıdan veri alırken iki şekilde alabiliriz. Bu yöntemler GET ve POST metodlarıdır. Aralarında bazı farklar vardır. GET ile alınan tüm veriler tarayıcının adres çubuğunda görülür ve yaklaşık olarak 2KB civarında boyut sınırlaması vardır. POST metodu ise verileri tarayıcıya doğrudan gönderdiği için gönderilen veriler adres çubuğunda görünmez. Herhangi bir boyut sınırlaması da yoktur.
GET Metodu
yonetim/views.py dosyasına arama görünümü ekleyelim.
from django.http import *
def Arama(request):
 if request.method == "GET":
  kelime = request.GET['kelime']
  return HttpResponse('Aranan Kelime:  %s' % (kelime))
Tarayıcıdan http://localhost:8000/arama/?kelime=deneme girdiğiniz zaman çıktıyı alacaksınız.
Aranan Kelime: deneme
Burada dikkat etmemiz gereken veriyi request.GET['kelime'] metodu ile aldığımız için eğer kelime girilmemiş ise yani tarayıcıdan http://localhost:8000/arama/ girilirse hata ile karşılaşırız. Burada hata ile karşılaşmamak için request.GET.get('kelime') metodunu kullanmalıyız. Eğer veri girilmedi ise boş değer döndürür.
### views.py
def arama(request):
 if request.method == "GET":
  kelime = request.GET.get('kelime')
  return HttpResponse('Aranan Kelime:  %s' % (kelime))
##Taryıcı adres çubuğu
http://localhost:8000/arama/
### Çıktı
Aranan Kelime: None
Gördüğünüz gibi hata ile karşılaşmadık. Aslında herhangi bir adrese girildiğinde biz işlem yapmasak bile GET metodu çalışır.
POST Metodu
Şimdi POST metodunu anlayabilmek için aynı örneğin form uygulamasını yapalım. Formlara daha ayrıntılı şekilde bakacağız. İlk önce yonetim/sablonlar içerisine get_post.html adında bir şablon oluşturuyoruz.
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>

<form action="/arama-post/" method="post">
    {% csrf_token %}
    Aranacak kelime : <input type="text" name="kelime" />
    <input type="submit" value="Ara" />
</form>


</body>
</html>
Şimdi yonetim/views.py dosyasına şu görünümü ekliyoruz.
from django.http import *
from django.template import RequestContext
def arama_post(request):
 if request.method == "POST":
  kelime = request.POST['kelime']
  return HttpResponse('Aranan kelime: %s'%(kelime))
 else:
  return render_to_response('get_post.html',context_instance=RequestContext(request))
urls.py
url(r'^arama-post/',yonetim.views.arama_post),
Şimdi tarayıcıdan localhost:8000/arama-post yazarak arama formuna ulaşabilirsiniz. Görünümde yaptığımız işlem eğer POST işlemi yapıldıysa kelimeyi kelime = request.POST['kelime'] satırı ile elde ediyoruz. HttpResponse ile ekrana basıyoruz. Eğer POST işlemi yapılmadıysa get_post.html şablonunu ekrana yazdırıyoruz.
Kaynakça :

22 Mart 2014 Cumartesi

URL Hakkında Bilgiler

Formlar konusuna geçmeden önce URL hakkındaki bazı bilgileri ulaşmayı görelim. HTTPRequest nesneleri URL hakkında çeşitli bilgileri içerir. Bulunduğumuz adresin yolunu almak için request.path özelliğini kullanabilir. Bulunduğumuz adresin yolunu almak için görünüm oluşturalım.
def yol(request):
 yol = request.path
 return HttpResponse('Adres Yolu: %s' % (yol))
Görünüme ulaşabilmek için urls.py ekleyelim.
url(r'adres-yolu/',yonetim.views.yol),
Adres çubuğuna localhost:8000/adres-yolu yazdığınızda şu şekilde bir çıktı alacaksınız.
Adres Yolu: /adres-yolu/
O anda adres çubuğunda bulunduğumuz yerin adresini bu şekilde aldık. Dikkat ederseniz host name kısmı alınmadı.
Özellik/MethodAçıklamaÖrnek
request.get_host()Hostname ulaşmak için kullanılır.localhost:8000
request.get_full_path()Tam yolu almak için kullanılır. Tarayıcıdaki verilen parametrelerde görülür.Tarayıcı : http://localhost:8000/adres-yolu/?get=deneme
Method'un dönüş değeri : /adres-yolu/?get=deneme
request.is_secure()Eğer HTTPS protokolü kullanılıyorsa True döndürür. HTTP protokolü kullanılıyorsa False döndürür.False
Request Değerinin Diğer Özellikleri
Oluşturduğumuz bir görünümde argüman olarak aldığımız request(istek) değişkenin çeşitli az önce bahsettiklerimiz gibi çeşitli metodları vardır. Buradaki request yerine istediğiniz değişken ismini verebilirsiniz. Biz sadece geleneklere uymak için request olarak kullanacağız.
def gorunum(request):
request.META
request.Meta kullanıcının ip adresi, kullandığı tarayıcı, sunucu adı, sunucunun kullandığı protokol gibi pek çok bilgiyi içeren bir sözlüktür.
  • HTTP_USER_AGENT Tarayıcı hakkında bilgi verir.
  • REMOTE_ADDR Kullanıcı ip adresi.
  • SERVER_PORT Sunucunun kullandığı port numarası.
Bu şekilde pek çok anahtar içermektedir. Bu anahtarların ve değerlerinin hepsine şu şekilde ulaşabilir ve istediğinizi kullanabilirsiniz.

def display_meta(request):
    values = request.META.items()
    values.sort()
    html = []
    for k, v in values:
        html.append('%s%s' % (k, v))
    return HttpResponse('%s
' % '\n'.join(html))
Bu kısım biraz bizi uğraştırdığı için sizin de aynı sorunlar ile karşılaşacağınızı düşündüğümüz için ayrı bir yazı olarak yazmaya karar verdik. Yönetim paneline giriş yaparsanız sizi şu şekilde bir pencere karşılaşacaktır.
Burada gördüğünüz gibi Sites bölümü bulunmuyor. Şimdi bu bölümü aktifleştirmeyi göreceğiz. Bu bölümün aktif olmamasının sebebi settings.py dosyasında INSTALLED_APPS kısmında uygulamaları yüklerken bu uygulamayı yüklememiş olmamızdır.
'django.contrib.sites',
Bu ifadeyi ekleyelim ve INSTALLED_APPS demetinin son hali şu şekilde olsun.
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
 'yonetim',
)
Bu işlemi yaptıktan sonra Yönetim Paneli'ne Sites bölümünün geldiğini göreceksiniz.
Ama burada siteler bağlantısına tıkladığınızda no such table: django_site şeklinde bir hata alacaksınız. Bunun sebebi ise; veritabanı oluştururken az önce eklediğimiz uygulama projemize ekli olmadığı için uygulamaya ait olan django_site tablosunun oluşturulmamış olmasıdır.
python manage.py syncdb
komutunu vererek veritabanını tabloları oluşturmalıyız. Artık Sites bölümünden sitemiz ile ilgili ayarları yapabiliriz.
Bu işlemleri yaptıktan sonra settings.py dosyasına şu satırı ekliyoruz.
SITE_ID=1

20 Mart 2014 Perşembe

Yönetim Paneli

Django'nun en güçlü taraflarından biri otomatik gelen yönetim panelidir. Daha önce herhangi bir dil ile web sitesi yaptıysanız kendinize yönetim paneli yazmanız gerektiğini biliyorsunuzdur. Yönetim paneli çoğunlukla veritabanı içerisindeki yazılara,kategorilere, yorumlara müdahale etmek için kullanılan bir paneldir. Açıkçası bir web sitesi yapmanın en can sıkıcı taraflarından biri yönetim paneli yapmaktır. İşte Django bize burada muhteşem bir kolaylık sağlıyor ve yönetim panelini hazır bir şekilde kullanımımıza sunuyor. Yönetim panelinin amacı her zaman aynıdır. Ekstra durumlar pek fazla bulunmaz. Veritabanına müdahale etmek için kullanılır. Django geliştiricileri bu rutin işlemleri bizim için düşünmüşler.
Yeni oluşturduğunuz bir projenin settings.py dosyasını açarsanız şu kısmı göreceksiniz.
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)
Yönetim(admin) uygulaması projeye dahil edilmiş bir şekilde gelmektedir. urls.py dosyası içerisinde tanımlı bir şekildedir.
from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
)
admin uygulaması django.contrib modülünün bir parçasıdır. INSTALLED_APPS değişkenine baktığınız zaman admin uygulamasından başka olarak sessions,messages gibi başka uygulamaları da barındırmaktadır. Tarayıcıda localhost:8000/admin yazdığınızda yönetim paneline ulaşırsınız. İsterseniz değiştirebilirsiniz.
urlpatterns = patterns('',
    url(r'^yonetim/', include(admin.site.urls)),
)
Artık localhost:8000/yonetim diyerek ulaşabiliyoruz. Yönetim panelini açtığınız zaman kullanıcı adını ve şifresini soran bir sayfa ile karşılaşacaksınız. Buradaki kullanıcı adını ve şifreyi daha önce atamıştık. İsterseniz yeni bir proje üzerinden hatırlayalım.
İlk önce Okul adında bir proje oluşturuyoruz.
django-admin.py startproject Okul
Aslında bunları yazmamıza gerek yok ama biz yinede sıradan gidelim. Projemizi oluşturduktan sonra porje içerisinde yonetim uygulamasını oluşturuyoruz.
python manage.py startapp yonetim
Uygulamayı oluşturduktan sonra yonetim/models.py dosyasını açalım ve okul ile ilgili modelimiz oluşturalım.
from django.db import models

class OgretimElemani(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 eposta = models.EmailField(blank=True)

 def __unicode__(self):
  return u'%s, %s'%(self.soyadi,self.adi)


class Dersler(models.Model):
 adi = models.CharField(max_length=50)
 ogretim_elemani = models.ForeignKey(OgretimElemani)

 def __unicode__(self):
  return u'%s'%(self.adi)


class Ogrenciler(models.Model):
 adi = models.CharField(max_length=50)
 numarasi = models.CharField(max_length=50)
 dersler = models.ManyToManyField(Dersler)

 def __unicode__(self):
  return u'%s, %s'%(self.adi,self.numarasi)
Modeli oluşturduğumuza göre artık tabloları oluşturabiliriz. Bildiğiniz gibi komut satırına şu komutu yazıyoruz.
python manage.py syncdb

Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table yonetim_ogretimelemani
Creating table yonetim_dersler
Creating table yonetim_ogrenciler_dersler
Creating table yonetim_ogrenciler

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): 
Tabloları oluşturduktan sonra bize yetkili bir kullanıcı oluşturmak isteyip istemediğimizi soruyor. Bu soruya yes dedikten sonra username(kullanıcı adı), e-posta(Email address) ve şifre(password) istiyor. Burada kullanıcı adını ve E-posta kısımlarını doldurmak zorunda değilsiniz. Eğer kullanıcı adını doldurmazsanız varsayılan olarak root olacaktır. Şifre kısmını iki kere girmek zorundasınız. Şifreyi de girdikten sonra süper kullanıcı oluşturulur.
python manage.py runserver
komutu ile projeyi server üzerinde çalıştırdıktan sonra tarayıcıya localhost:8000/admin yazarak yönetim paneline ulaşın. Karşınıza şu şekilde bir pencere gelecektir.
Burada oluşturmuş olduğunuz kullanıcı adı ve şifre ile giriş yaparak yönetim paneline girebilirsiniz. Eğer giremiyorsanız süper kullanıcı oluşturduğunuzdan emin olun. Eğer süper kullanıcı oluşturmadıysanız şu komut ile oluşturabilirsiniz.
python manage.py createsuperuser
Giriş yaptıktan sonra kullanıcıları düzenleyebileceğiniz bir sayfa ile karşılaşacaksınız. Fakat bu sayfa İngilizce ilk önce sayfayı Türkçe yapalım. settings.py dosyası içerisindeki LANGUAGE_CODE değişkenini şu hale getirelim.
LANGUAGE_CODE = 'tr-TR'
Artık sayfamız türkçe ama oluşturduğumuz veritabanı ait tabloları göremiyoruz. Bu alanları eklemek zorundayız. İlk önce settings.py içerisindeki INSTALLED APPS değişkenine oluşturduğumuz uygulamayı ekliyoruz.
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
 'yonetim',
)
Ekleme işlemini yaptıktan sonra yonetim uygulaması içerisindeki admin.py dosyasına şu satırları ekliyoruz.
from django.contrib import admin

from yonetim.models import *

admin.site.register(OgretimElemani)
admin.site.register(Dersler)
admin.site.register(Ogrenciler)
Sayfayı yenilediğiniz zaman yonetim uygulaması içeriğinin geldiğini göreceksiniz.
Yönetim paneli bize kullanıcılar,gruplar ve veritabanları üzerinde işlemler yapma olanağı verir.
Django'nun yönetim paneli her uygulama içerisindeki admin.py içerisine bakar ve eklemesi gereken yerleri -veritabanı alanları- gibi kendi içerisine ekler ve kullanıcıya üzerlerinde işlem yapma olanağı verir.
Kaynakça

18 Mart 2014 Salı

Q Nesnesi ve Tam SQL Sorguları

Q Nesnesi
Sorgulamalarda filter() nesnesini kullanırken birden çok argüman gönderebiliyoruz. Bu gönderdiğimiz argümanlar arasına SQL'de and konur.
>>> doktorlar = Doktor.objects.filter(adi='Ahmet',ucret__lt=1500)
Buradaki filtreleme şu şekilde: Adi Ahmet olan ve ücreti en az 1500 olan Doktorları getir. Dikkat ettiyseniz ve kullandık. Yani sorgu şu şekilde.
Select * from Doktor where adi='Ahmet' AND ucret>1500)
Sorguda AND değilde OR kullanmak istiyorsak Q Nesnesini kullanacağız.
>>> from django.db.models import Q
>>> sorgu = Q(ucret=1500) | Q(ucret=2000)
>>> doktorlar = Doktor.objects.filter(sorgu)
>>> doktorlar
[<Doktor: Rıdvan , Durmaz>, <Doktor: Sevgi , Dönmez>]
Buradaki sorgumuz OR ile birleştirildi. Ücreti 1500 veya 2000 olan doktorları istemiş olduk. SQL sorgusu şu şekilde olacak.
Select * from Doktor Where ucret=1500 OR ucret=2000
Bu sorgulamayı Q Nesnesini kullanmadan şu şekilde de yazabildik.
doktorlar = Doktor.objects.filter(ucret=1500) | Doktor.objects.filter(ucret=2000)
Tam SQL Soguları
Bazen sorgulama yaparken Django'nun bize sunduğu Model sorgulamaları işimizi görmeyebilir. Böyle durumda SQL sorgusunu doğrudan yazarak sorgulama yapabiliriz.
>>> for doktor in Doktor.objects.raw('Select * from ucret_Doktor'):
...     print doktor
Ahmet , Mehmet
Rıdvan , Durmaz
Sevgi , Dönmez
Bu şekilde doğrudan SQL sorguları üzerinden çalışabiliriz.
Not: Sorgu içerisindeki ucret_Doktor kısmındaki ucret uygulamanın adını Doktor ise tablonun adını belirtir.
Eğer istersek sorgudan dönen ilk satırı şu şekilde alabiliriz.
>>> doktor = Doktor.objects.raw('Select * from ucret_Doktor')[0]
>>> doktor
<Doktor: Ahmet , Mehmet>
Dışarıdan değer alabileceğimiz bir sorgulama yapalım.
>>> min_ucret=1500
>>> for doktor in Doktor.objects.raw('Select * from ucret_Doktor where ucret>%s' %min_ucret):
...     print doktor
Rıdvan , Durmaz
SQL sorgularını bir Modele bağlı kalmadan doğrudan işletebiliriz.
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute('Select * from ucret_Doktor')
>>> row = cursor.fetchone()
>>> row
(1, u'Ahmet', u'Mehmet', 1000)
Buradaki fetchone() yerine fetchall() kullanarak tüm satırları döndürebiliriz. Burda cursor.executu() ile istediğimiz sorguyu çalıştırabiliriz.
>>> cursor.execute('Insert into ucret_Doktor(adi,soyadi,ucret) values("Selcuk","Inan",3000)')
>>> veri = cursor.execute('select * from ucret_Doktor')
>>> doktorlar = cursor.fetchall()
>>> doktorlar
[(1, u'Ahmet', u'Mehmet', 1000), (2, u'R\u0131dvan', u'Durmaz', 2000), (3, u'Sevgi', u'D\xf6nmez', 1500), (4, u'Selcuk', u'Inan', 3000)]
Gördüğünüz gibi ekleme sorgusu başarı ile çalıştı.
Kaynakça

16 Mart 2014 Pazar

Sorgulama Seçenekleri

Modellerden veri çekerken sorgulama için objects.filter() fonksiyonunu kullanmıştık. Bu bölümde filter() fonksiyonuna ait bazı özelliklerden bahsedeceğiz.
exact
Tam eşleştirme yapar.
>>> doktor = Doktor.objects.filter(adi__exact='Ali')
>>> doktor
[<doktor: ali="" hikmet="" mail.com="">]
Sorgusu ise şu şekilde olacaktır.
Select * from Doktor where adi='Ali';
iexact
Eşleştirme yaparken büyük küçük harf duyarsızlığı vardır.
>>> doktor = Doktor.objects.filter(adi__iexact='ali')
>>> doktor
[<Doktor: Ali , hikmet ,ali@mail.com>]
contains
Kelime grubu içerisinde arama yapar. Eğer kelime içerisinde aranan alt kelime varsa geriye döner.
>>> doktor = Doktor.objects.filter(adi__contains = 'a')
>>> 
>>> dokto
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Ali , hikmet ,ali@mail.com>]
Sorgusu;
Select * from Doktor WHERE adi LIKE '%a%';
icontains
Aramayı duyarsız hale çevirir.
in
Aramayı liste içerisinden yapar.
>>> polikilinik = Polikilinik.objects.filter(kodu__in=['P404','P505'])
>>> polikilinik
[<Polikilinik: P404 , Serdivan >, >Polikilinik: P505 , İstanbul >]
gt
Girilen değerden daha büyük değerleri getirir.
>>> doktor = Doktor.objects.filter(id__gt=2)
>>> doktor
[<Doktor: Ali , hikmet ,ali@mail.com>]
idsi 2'den büyük olan doktorları listeledik.
gte
Girilen değere eşit veya daha büyük verileri getirir.
>>> doktor = Doktor.objects.filter(id__gte=2)
>>> doktor
[<Doktor: Veli , Kırmızı ,veri@mail.com>, <Doktor: Ali , hikmet ,ali@mail.com>]
id'si 2 veya daha büyük olan doktorları getirdik
lt ve lte
lt: Daha küçük veriler. lte: Eşit veya daha küçük veriler.
>>> doktor = Doktor.objects.filter(id__lt=2)
>>> doktor
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>]
startswith ve istartswith
startswith: Girilen değer ile başlayan verileri getirir. istartswith: Girilen değer ile başlayan verileri duyarsız bir şekilde getirir.
>>> doktor = Doktor.objects.filter(adi__startswith='A')
>>> doktor
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Ali , hikmet ,ali@mail.com>]
endswith ve iendswith
endswith: Girilen değer ile biten verileri getirir. iendswith: Girilen değer ile biten verileri duyarsız bir şekilde getirir.
>>> doktor = Doktor.objects.filter(adi__endswith='A')
>>> doktor
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Ali , hikmet ,ali@mail.com>]
range
Girilen aralıktaki değerleri getirir.
import datetime
baslangic = datetime.date(2005, 1, 1)
bitis = datetime.date(2005, 3, 31)
Doktor.objects.filter(giris_tarihi__range=(baslangic, bitis))
Sorgusu
Select * from Where giris_tarihi '2005-01-01' Between '2005-03-31';
year
Yıl sorgulaması yapar.
Doktor.objects.filter(giris_tarihi__year=2013)
month
Yıl sorgulaması yapar.
Doktor.objects.filter(giris_tarihi__month=10)
day
Yıl sorgulaması yapar.
Doktor.objects.filter(giris_tarihi__day=18)
HESAPLAMA FONKSİYONLARI
Sorgulama işlevi yaparken kullanabileceğimiz hesaplama fonksiyonlarına bakalım.
count
Sayma işlemi yapar.
##Doktor sayısını bulalım
>>> doktor_sayisi = Doktor.objects.all().count()
>>> doktor_sayisi
3
Avg
Ortalama hesaplar.
###Doktorların maaş ortalaması
>>> from django.db.models import Avg
>>> ucret_toplami = Doktor.objects.all().aggregate(Avg('ucret'))
>>> ucret_toplami
{'ucret__avg': 1500.0}
Max
En büyüğü bulur.
###En yüksek doktor maaşı
>>> from django.db.models import Max
>>> yuksek_ucret = Doktor.objects.all().aggregate(Max('ucret'))
>>> yuksek_ucret
{'ucret__max': 2000}
Min
En küçüğü bulur.
###En düşük doktor maaşı
>>> from django.db.models import Min
>>> dusuk_maas = Doktor.objects.aggregate(Min('ucret'))
>>> dusuk_maas
{'ucret__min': 1000}
Sum
Toplamı bulur.
###Doktorların toplam maaşı
>>> from django.db.models import Sum
>>> toplam_maas = Doktor.objects.aggregate(Sum('ucret'))
>>> toplam_maas
{'ucret__sum': 4500}
Kaynakça

14 Mart 2014 Cuma

Statik Dosyalar

Eğer daha önceden web sitesi geliştirdiyseniz, projenize statik dosya eklemişsiniz demektir. Statik dosyalar resim,*.pdf,*.txt, gibi dosyalardır. Bunların yanında bizim için son derece önemli olan css dosyaları da statik dosyalardır. Daha önceden yaptığımız hastahane projesi üzerinden gidersek hastahane/settings.py dosyasını açarsanız. Şu şekilde bir satır göreceksiniz.
STATIC_URL = '/static/'
Bu statik dosyaların yerinin static dizini olacağını belirtiyor. Oluşturulan tüm uygulamalar içerisindeki static dizinleri içerisine bakılması için aşağıdaki kod parçasını urls.py içerisine şu kod parçasını ekleyin.
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Bu kod parçası sayesinde biz tarayıcı da şu şekilde bir adres girdiğimi zaman
http://localhost:8000/static/kim-korkar-linuxtan.pdf
tüm uygulamalar içerisindeki static dizini altında kim-korkar-linuxtan.pdf dosyası aranacaktır. URL'deki static adresini STATIC_URL değişkenine istediğiniz değeri atayarak değiştirebilirsiniz.
Tabi bu şekilde tüm uygulamalar içerisindeki static dizinlerine teker teker bakılması doğru değildir. Tüm statik dosyaların tek bir dizin içerisinde toplanarak istenildiği zaman o dizinden çekilmesi daha doğru olacaktır. Tüm statik dosyaları dosyalar dizini içerisinde toplayalım. Bu dizin projenin ana dizini içerisinde olacaktır. Şimdi Django'nun bu yolu bulabilmesi için settings.py dosyası içerisine şu satırları ekliyoruz.
STATICFILES_DIRS = (
 os.path.join(anadizin,'dosyalar'),
)

STATIC_URL = '/dosyalar/'
Dosyalarımızı artık bu dizinde saklayacağız. STATIC_URL değişkenini de değiştirdik. Yani tarayıcıdan bir dosyaya ulaşmak için
http://localhost:8000/dosyalar/resim.jpg
yazımını kullanmamız gerekiyor.
Şimdi daha önceden yaptığımız Doktor Listesi sayfası içerisine .css dosyası ekleyelim. Yapmamız gereken dosyalar dizini içerisine style.css dosyası oluşturmak ve içerisine şu kodları yazmak.
table {
    border: 1px solid #ddd;
    border-radius: 5px;
}

table td,th,tr {
    padding: 5px;
}

table th {
    background: #234f32;
    color: #fff;
}
Şimdi css dosyamızı doktor_listesi.html dosyasına göstermemiz gerekiyor. Bunun için <head></head> etiketleri arasına şu kodu ekliyoruz.
<link href="/dosyalar/style.css" rel="stylesheet" type="text/css" />
Artık yeni görünümümüzü elde etmiş olduk.
Statik dosyalar sayesinde sitemize css dosyası eklemiş olduk.
Kaynakça

12 Mart 2014 Çarşamba

Modelleri görünümler ile kullanmanın daha önce yaptıklarımızdan pek bir farkı yoktur. Daha önce bir tablo içerisinden verileri şu şekilde almıştık.
doktorlar = Doktor.objects.all()
İşte bu şekilde aldığımız verileri görünüm(view) içerisinden şablonlara(template) aktaracağız ve kullanıcıya göstereceğiz. İlk önce şablonlarımızı saklayacağımız dizini oluşturalım.
yonetim/sablonlar
Şimdi şablon dizinin yolunu settings.py dosyası içerisine ekleyelim. TEMPLATE_DIRS değişkenine şu satırı ekliyoruz.
TEMPLATE_DIRS = (
os.path.join(anadizin,'yonetim/sablonlar')
)
Buradaki anadizin değişkenini daha önceden tanımlamıştık. İsterseniz bi hatırlayalım.
dizin = os.path.dirname(__file__)
anadizin = os.path.split(dizin)[0]
Oluşturduğumuz yonetim uygulaması içersinden sablonlar dizinini oluşturuyoruz. Şablonlarımız burada saklayacağız. Doktorları listeleyecek bir görünüm hazırlayacağız. yonetim içersindeki views.py dosyasına şu kodları ekliyoruz.
## models dosyasını içe aktarıyoruz
from models import *


def Doktor_listesi(request):
        ## Daha önce kullandığımız Doktor.objects.all() fonksiyonu ile verileri doktorlar değişkenine atıyoruz.
 doktorlar = Doktor.objects.all()
 return render_to_response('doktor_listesi.html',locals())
Şimdi doktor_listesi.html şablonunu oluşturuyoruz. Şablonun yonetim/sablonlar dizininde olmasına dikkat edin.
<!DOCTYPE html>
<html>
<head>
    <title>Doktorlar Listesi</title>
</head>
<body>

<table border="1">
    <tr><th>Sıra</th><th>Adi</th><th>Soyadi</th><th>Telefon</th><th>E-Posta</th></tr>

    {% for doktor in doktorlar %}
    <tr>
        <td>{{ doktor.adi }}</td>
        <td>{{ doktor.soyadi }}</td>
        <td>{{ doktor.telefon }}</td>
        <td>{{ doktor.eposta }}</td>
    </tr>
    {% endfor %}

</table>

</body>
</html>
Geriye sadec url'i eklemek kaldı. hastahane/urls.py dosyasını açarak aşağıdaki kodları ekliyoruz.
##yonetim uygulaması içerisindeki views dosyasını içe aktarıyoruz
import yonetim.views

### url kımsını ekliyoruz.
url(r'^doktorlar/',yonetim.views.Doktor_listesi),
hastahane/urls.py dosyasının son hali şu şekilde olacaktır.
from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

import yonetim.views

urlpatterns = patterns('',

    url(r'^admin/', include(admin.site.urls)),
 url(r'^doktorlar/',yonetim.views.Doktor_listesi),
)
url'i de eklediğimize göre artık adresimize ulaşabiliriz. Şimdi tarayıcıya
http://localhost:8000/doktorlar/
adresini girelim. Aşağıdaki gibi bir çıktı alacağız.
Modelleri şablonlar ile kullanmak bu kadar basit. Sizde daha farklı uygulamalar yaparak kendinizi deneyebilirsiniz. Kaynakça

9 Mart 2014 Pazar

Django 1.3 sürümünden itibaren Class Based Views (Sınıf Tabanlı görünüm) konsepti gündeme geldi.  Bu şekilde view fonksiyonlarının yerini python objeleri alır.
Specific HTTP metodları ayrı methodlarla belirlenebilir, nesne tabanlıteknikleri (mixins) gibi daha çok kullanılabilir.

Önce Python’da fonksiyon ve method farkını bir örnekle görelim:
class PrintMe(object):
    def __init__(self, astring):
        self.l = astring 
    def print_me(self):
        print(self.l)
Metodu çalıştıralım:
p = PrintMe("po")
p.print_me()
Fonksiyon:
def print_me(l):
    print l
Fonksiyonu çalıştıralım:
print_me("po")
Ve çıktılar:


Django'da bir HTTP GET için , bir view (görünüm) fonksiyonu şu şekilde:
from django.http import HttpResponse

def any_view(request):
    if request.method == 'GET':
        # kodlarınız
        return HttpResponse('any responce')

CBV’de (Class Based Views) ise :
from django.views.generic import View
class AnyView(View):
    def get(self, request):
        # kodlarınız
        return HttpResponse('any responce')
urls.py’da :
from django.conf.urls import patterns
from anyapp.views import AnyView

urlpatterns = patterns('',
    (r'^any/', AnyView.as_view()),
)

CBV’de, get ve post methodları:
Bir CBV’de, get ve post methodunun argumanları, self , request (HttpRequest) ve URLconf’da belirlediğiniz request argumanıdır:
from django.views.generic import View
class ViewClass(View):
    def get(self, request, arg1, keyword=value):
        return method1()
    def post(self, request, arg1, keyword=value):
        return method2()


Kaynakça:
https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/
http://lgiordani.github.io/blog/2013/10/28/digging-up-django-class-based-views-1/
http://programmer.97things.oreilly.com/wiki/index.php/Don't_Repeat_Yourself

Model Alan Tipleri

Veritabanı Yapılandırması yazısında Model oluştururken bazı alan tiplerini kullanmıştık. Şimdi kullanabileceğimiz tüm alan tiplerinden kısaca bahsedelim.
BigIntegerField
64 bit sayı tutar. IntegerField gibidir. Fakat -9223372036854775808-9223372036854775807 arasında sayı saklayabilir. Formda <input type="text" /> alanı oluştur.
BooleanField
Doğru/Yanlış alanıdır. Formda <input type="checkbox" /> alanı oluşturur. Eğer boş bir doğru/yanlış alanı istersek NullBooleanField kullanabiliriz.
CharField
Metin alanıdır. Formda <input type="text" /> alanı oluşturur. max_lenght parametresi ile girilebilecek maximim karakter sayısı verilebilir. Uzun metinler için TexField kullanılır.
CommaSeparatedIntegerField
Kullanıcan binlik basamakları ayırt etmek için virgül kullanmasını istiyorsak kullanabiliriz. Bu alanda max_lenght parametresi ile uzunluğu belirtilmelidir.
DateField
Python'da ki datetime.date nesnesinin verdiği değer tipinde veri saklamak için kullanılır. Formda <input type="text" /> alanı oluşturur.
DateField.auto_now : Bağlı bulunduğu model nesnesi her kaydedildiğinde o andaki zamanı kaydeder.
DateField.auto_now_add : Bağlı bulunduğu nesne ilk oluşturulduğu andaki zamanı saklamak için kullanılır.
DateTimeField
Python'da ki datetime.datetime nesnesinin verdiği değer tipinde veri saklamak için kullanılır. Formda <input type="text" /> alanı oluşturur. DateFiel ile aynı parametreleri alır.
DecimalFiel
Ondalıklı sayıları saklamak için kullanılır. Formda <input type="text" /> alanı oluşturur. max_digits ve decimal_places parametreleridir.
max_digits : En fazla rakam sayısı.
DateField.auto_now_add : Ondalık kısım miktarı.
models.DecimalField(max_digits=50, decimal_places=10)
EmailField
CharField alanıdır. Doğru bir e-posta girilmesini ister.
FileField
Dosya alanıdır. Formda <input type="file" /> alanı oluşturur. Bu alan upload_to parametresi alır. Bu parametrenin değeri setting.py dosyasında belirtilen MEDIA_ROOT değişkeninde belirtilen patikaya eklenir. Örneğin MEDIA_ROOT = /home/mazlumagar/ ve upload_to='dosyalar' ise dosyanın yüklenme yeri /home/mazlumagar/dosyalar olur.
FloatField
Float tipinde sayıları saklamak için kullanılır. Form'da <input type="text" /> alanı oluşturur.
ImageField
FileField alanı gibidir. Ancak resim dosyaları için kullanılır.
IntegerField
Tam sayı alanıdır. Form'da <input type="text" /> alanı oluşturur.
IPAddressField
IP adresi saklamak için kullanılır. Form'da <input type="text" /> alanı oluşturur.
PositiveIntegerField
Pozitif tam sayı alanıdır. Form'da <input type="text" /> alanı oluşturur.
TextField
Uzun metinler için kullanılır. Form'da <textarea></textarea> alanı oluşturur.
URLField
CharField alanıdır. Fakat URL saklamak için kullanılır.

6 Mart 2014 Perşembe

Veritabanı Yapılandırması

Veritabanı yapılandırması için proje içerisinde bulunan settings.py dosyası kullanılır. Bu dosya içerisindeki DATABASE bölümü default olarak şu şekilde gelmektedir.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
Gördüğünüz gibi veritabanı olarak varsayılan bir biçimde sqlite3 gelmektedir. Varsayılan olarak gelen parametreler dışında kalan parametreleri inceleyelim.
Parametreİşlevi
ENGINEKullanılacak veritabanı sistemi belirtilir.
NAMEVeritabanı ismini içerir.
USERVeritabanı kullanıcısını içerir.
PASSWORDKullanıcı şifresini içerir.
HOSTVeritabanı adresini içerir. Eğer veritabanı yerel makina ile aynı yerde ise boş bırakılır.
PORTVeritabanı standart portunu değil de başka bir portu dinliyorsa PORT numarasını içerir.
Kullanılan veritabanı sistemini ENGINE parametresi ile belirtiyoruz. Veritabanı belirtilmeden önce django.db.backends. takısı ardından veritabanı parametresi yazılır. Kullanılan veri tabanları şu şekildedir:
AyarVeritabanı
django.db.backends.postgresql_psycopg2PostreSQL
django.db.backends.mysqlMYSQL
django.db.backends.sqlite3SQLite
django.db.backends.oracleOracle
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '/veritabani/ornek.db',
  'USER':'mazlum',
  'PASSWORD':'123',
  'HOST':'',
  'PORT':''
    }
}
Veritabanı ismi verilirken veritabanının tam yolu belirtilmelidir.
İlk Model Uygulamamız
Yeni bir örnek çalışma yaparak modelleri bu örnek çalışma üzerinden anlatalım. Küçük bir hastahane otomasyonu yapacağız.
Projemizi oluşturalım.
django-admin.py startproject hastahane
Veritabanı olarak SQLite kullanacağız. Herhangi bir sunucu gereksinimi olmadan çalıştığı için veritabanı sunucu yönetimine gerek kalmadan veritabanı işlemlerimizi halledebileceğiz. Veritabanı dosyası proje dosyamız içerisinde olacağından taşınması gibi durumlarda herhangi bir sorun ile karşılaşmayacağız.
Veritabanı yolunu sistematiksel bir hale getirmek için projemizin ana dizinini bir değişkene atalım. Projemiz içerisindeki settings.py içerisine şu kodları ekliyoruz.
import os.path
dizin = os.path.dirname(__file__)
anadizin = os.path.split(dizin)[0]
DATABASES sözlüğünü kendi projemize göre düzenliyoruz.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(anadizin, 'db/hastahane.db'),
  'USER': '',
  'PASSWORD':'',
  'HOST':'',
  'PORT':''
    }
}
NAME parametresini veritabanın tam yolunun yazılması gerektiğini unutmamalısınız. Doğrudan yol şeklinde de yazabilirsiniz. Ama projenizin yerini değiştirdiğiniz de NAME parametresini tekrar düzenlemeniz gerekir. Eğer düzenlemezseniz veritabanı bulunamadığı için hata verir. Biz bu problemleri aşabilmek için yolu bulma işin Python'a bıraktık.
Veritabanını projenin ana dizini içerisinde veritabani klasörü içerisinde saklayacağız. Yani veritabanımızın yolu /home/mazlumagar/Django/hastahane/veritabani/hastahane.db şeklinde olacaktır. Projelerdeki karmaşılığın üstesinden gelebilmek için Django'da uygulamalar oluşturulur. Veritabanı işlemlerini yapabilmek için uygulama oluşturacağız. Veritabanı işlemlerini yapabileceğimiz yonetim uygulamasını oluşturalım.
python manage.py startapp yonetim
Bu komut ile projemiz içerisinde şu şekilde bir yapı oluşacaktır.
yonetim/
        __init__.py
        models.py
        tests.py
        views.py
        admin.py
Projemizin uygulamamızı tanıması için eklememiz gerekiyor. hastahane/hastahane/settings.py dosayasına INSTALLED_APPS değişkenine 'yonetim', satırını ekleyeceğiz. Son hali şu şekilde olacak.
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
 'yonetim',
)
Ön tanımlı olarak başka uygulamarında projemize dahil edildiğini görebilirsiniz.
İlk Modelimiz
Daha önce bahsetmiştik. Django ile proje geliştirirken SQL sorguları ile uğraşmayacağız. Ama veritabanı mantığını ve işleyişini bilmemiz gerekiyor. SQL sorgularının Django tarafından otomatik yapılabilmesi için tanımlamalar yapmamız gerekiyor. İşte bu tanımlamalara Model denir. Hastahane projemizin veritabanı sistemi şu şekilde olacak.
hasta_polikilinik tablosunun ilişkilerden oluştuğunu görüyorsunuz. Modelimizi oluşturmak için yonetim/models.py dosyasını açarak ilk Model tanımlamamızı yapıyoruz.
from django.db import models


class Doktor(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 telefon = models.CharField(max_length=50,blank=True)
 eposta = models.EmailField(blank=True)

class Polikilinik(models.Model):
 kodu = models.CharField(max_length=20)
 adi = models.CharField(max_length=50)
 doktor = models.ForeignKey(Doktor)

class Hasta(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 hasta_polikilinik = models.ManyToManyField(Polikilinik)
Alan türlerini konunun en sonunda tablo şeklinde vereceğiz. Bir alanın boş bırakılabilir olması için blank=True değerini argüman olarak göndermemiz gerekiyor. Doktor tablosunda adı ve soyadı bölümü doldurulmak zorunda iken telefon ve eposta bölümleri boş bırakılabilir. Doktor modeli için Django şu SQL sorgusunu oluşturur.
CREATE TABLE "Doktor" (
 "id" integer NOT NULL PRIMARY KEY,
 "adi" varchar(50) NOT NULL,
 "soyadi" varchar(50) NOT NULL,
 "telefon" varchar(10),
 "eposta" varchar(75)
)
Bu sorgu SQLite içindir. Dikkat ettiyseniz id sütünü biz belirtmemize rağmen otomatik olarak oluştu. Django tablo oluştururken PRIMARY KEY(benzersiz) alanı kendisi oluşturur.
Tablolarımızın yapısını resim olarak gösterirken hasta_polikilinik adında bir tablomuz vardı. Biz model oluştururken o tabloya ait modeli oluşturmadık. Bu oluşturma işini Hasta modelindeki
hasta_polikilinik = models.ManyToManyField(Polikilinik)
satırı ile Django otomatik olarak yapar. Modellerimiz oluşturduğumuza göre herhangi bir hata var mı kontrol edelim.
python manage.py validate
Eğer çıktı 0 errors found şeklinde ise herhangi bir sorun yok demektir. Oluşturduğumuz modellere göre Django'nun oluşturacağı SQL sorgularını görebiliriz.
python manage.py sqlall yonetim
Bu komut ile tüm sorguları istediğimiz bir zamanda -tablolar oluşturulmuş olsa bile- görebiliriz.
BEGIN;
CREATE TABLE "yonetim_doktor" (
    "id" integer NOT NULL PRIMARY KEY,
    "adi" varchar(50) NOT NULL,
    "soyadi" varchar(50) NOT NULL,
    "telefon" varchar(50) NOT NULL,
    "eposta" varchar(75) NOT NULL
)
;
CREATE TABLE "yonetim_polikilinik" (
    "id" integer NOT NULL PRIMARY KEY,
    "kodu" varchar(20) NOT NULL,
    "adi" varchar(50) NOT NULL,
    "doktor_id" integer NOT NULL REFERENCES "yonetim_doktor" ("id")
)
;
CREATE TABLE "yonetim_hasta_hasta_polikilinik" (
    "id" integer NOT NULL PRIMARY KEY,
    "hasta_id" integer NOT NULL,
    "polikilinik_id" integer NOT NULL REFERENCES "yonetim_polikilinik" ("id"),
    UNIQUE ("hasta_id", "polikilinik_id")
)
;
CREATE TABLE "yonetim_hasta" (
    "id" integer NOT NULL PRIMARY KEY,
    "adi" varchar(50) NOT NULL,
    "soyadi" varchar(50) NOT NULL
)
;
CREATE INDEX "yonetim_polikilinik_72173312" ON "yonetim_polikilinik" ("doktor_id");
CREATE INDEX "yonetim_hasta_hasta_polikilinik_3ecb73da" ON "yonetim_hasta_hasta_polikilinik" ("hasta_id");
CREATE INDEX "yonetim_hasta_hasta_polikilinik_12325d4a" ON "yonetim_hasta_hasta_polikilinik" ("polikilinik_id");

COMMIT;
Herhangi bir sorun olmadığına göre ve sorgularımızı da gördüğümüze göre artık tablolarımızı oluşturabiliriz.
python manage.py syncdb
Creating tables ...
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table yonetim_doktor
Creating table yonetim_polikilinik
Creating table yonetim_hasta_hasta_polikilinik
Creating table yonetim_hasta
Tablolarımız oluşturduk.
NOT:Django bir model için bir tabloyu bir kere oluşturur. Yani model de yaptığımız değişiklik veritabanına yansımaz. Modeller tasarlanırken dikkatli olunmalı ve eksiksiz olmasını sağlamaya çalışmalıyız. Tablolardaki alanları değiştirme işini kendimiz elle yapmak zorundayız. Veri ekleme,silme ve güncelleme gibi sorgu işlemleri yapmak için Django kobuğunu açıyoruz.
python manage.py shell
Veri Ekleme
>>> from yonetim.models import *
>>> doktor1 =  Doktor(adi='Ahmet',soyadi='Mehmet',telefon='1111',eposta='doktor@mail.com')
>>> doktor1.save()
İlk doktoru tabloya eklemiş olduk. doktor1.save() satırını dikkat edin. Eğer bu şekilde kaydetme işlemini yapmaz isek alan tanımlaması yapılır fakat tabloya eklenmez. doktor1 yazdırarak bildi edinebiliriz.
doktor1
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>]
Daha detaylı bilgilendirme yapmak için. Model içerisinde __unicode__() işlevini tanımlamalıyız. Modelin yeni hali şu şekilde olacaktır.
class Doktor(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 telefon = models.CharField(max_length=50,blank=True)
 eposta = models.EmailField(blank=True)

 def __unicode__(self):
  return u'%s , %s ,%s' % (self.adi,self.soyadi,self.eposta)
Değişikliğin etkin olabilmesi için kabuğu yeniden başlatmalısınız. doktor1'i tekrar yazdıralım.
>>> doktor1
[<doktor: ahmet="" doktor="" mail.com="" mehmet="">]
Bir tablodaki tüm verileri alabilmek için objects.all() özelliği kullanılır. İlk önce bir kaç doktor daha ekleyelim.
>>> doktor2 = Doktor(adi='Ali',soyadi='Yılmaz')
>>> doktor2.save()
>>> doktor3 = Doktor(adi='Veysel',soyadi='Duran',eposta='veysel@mail.com'
>>> doktor3.save()
Şimdi Doktor tablosundan tüm verileri çekelim.
>>> doktorlar = Doktor.objects.all()
>>> doktorlar
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Ali , Yılmaz ,>, <Doktor: Veysel , Duran ,veysel@mail.com>]
Eğer istersek aldığımız tüm verilerin istediğimiz elemanına şu şekilde ulaşabiliriz.
>>> doktor1 = doktorlar[0]
>>> doktor1.adi
u'Ahmet'
Tüm modellerimize __unicode__() işlevini ekledik. models.py dosyamızın son hali şu şekilde olacak.
from django.db import models

class Doktor(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 telefon = models.CharField(max_length=50,blank=True)
 eposta = models.EmailField(blank=True)

 def __unicode__(self):
  return u'%s , %s ,%s' % (self.adi,self.soyadi,self.eposta)

class Polikilinik(models.Model):
 kodu = models.CharField(max_length=20)
 adi = models.CharField(max_length=50)
 doktor = models.ForeignKey(Doktor)


 def __unicode__(self):
  return u'%s , %s ' % (self.kodu,self.adi)

class Hasta(models.Model):
 adi = models.CharField(max_length=50)
 soyadi = models.CharField(max_length=50)
 hasta_polikilinik = models.ManyToManyField(Polikilinik)


 def __unicode__(self):
  return u'%s , %s ,%s' % (self.adi,self.soyadi,self.hasta_polikilinik)

Şimdi bir polikilinik ekleyelim.
pol1 = Polikilinik(kodu='P404',adi='Serdivan')
Polikilinik içerisindeki doktor alanı verilerini Doktor tablosundan çekiyor. Yani bir ilişki söz konusu olduğu için isim adi alanı gibi bir ekleme yapamazsınız. Deneyelim ve neler olacak bakalım.
pol = Polikilinik(kodu='P405',adi='Adapazari',doktor='Nazlı')
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 405, in __init__
    setattr(self, field.name, rel_obj)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/fields/related.py", line 327, in __set__
    self.field.name, self.field.rel.to._meta.object_name))
ValueError: Cannot assign "'Nazl\xc4\xb1'": "Polikilinik.doktor" must be a "Doktor" instance.
Gördüğünüz gibi Django bize doktor alanının Doktor tablosundan çekilmesi gerektiğini söylüyor.
Şimdi eklediğimiz ilk polikiliniğin doktorunu Doktor tablosundaki ilk doktor yapalım.
>>> pol1.doktor = doktorlar[0]
>>> pol1.save()
Bu şekilde daha anlaşılır olsun diye yolu uzattık. Daha kısa yoldan şu şekilde yapabilirsiniz.
>>> pol2 = Polikilinik(kodu='P405',adi='Adapazarı',doktor = doktorlar[1])
>>> pol2.save()
Şimdi bir kaç hasta ekleyelim ve bu polikilinikleri o hastaya ekleyelim.
>>> hasta1 = Hasta(adi='Mazlum',soyadi='Agar')
>>> hasta1.save()
>>> hasta2 = Hasta(adi='Yılmaz',soyadi='Gün')
>>> hasta2.save()
hasta1'e polikilinik ekleyelim.
>>> polikilinikler = Polikilinik.objects.all()
>>> hasta1.hasta_polikilinik.add(polikilinikler[0])
>>  hasta1.hasta_polikilinik.add(polikilinikler[1])
Hastaya polikilinik eklemiş olduk. Şimdi bunları görelim.
>>> hasta1.hasta_polikilinik.all()
[<Polikilinik: P404 , Serdivan >, <Polikilinik: P405 , Adapazarı >]
Gördüğünüz eklediğimiz polikilinikler hastada mevcut. İstersek silebiliriz.
>>> hasta1.hasta_polikilinik.remove(polikilinikler[1])
>>> hasta1.hasta_polikilinik.all()
[<Polikilinik: P404 , Serdivan >]
Veri Sorgulama
Önceki bölümde bir Tabloya ait tüm verileri çekmenin objects.all() özelliği ile yaptığımızı gördük. Şimdi filtreleme yaparak istediğimiz alanları çekelim. Bunun için objects.filter() özelliğini kullanacağız.
>>> doktor = Doktor.objects.filter(adi='Ali')
>>> doktor
[<Doktor: Ali , Yılmaz ,<]

Django bizim için şu sorguyu çalıştıracak.
Select * from Doktor where adi='Ali'
Birden fazla koşula bağlayabiliriz.
>>> doktor = Doktor.objects.filter(adi='Ali',soyadi='Yılmaz')
Sorugumuza bakalım.
Select * from Doktor where adi='Ali' and soyadi='Yılmaz'
Adından a harfi geçen doktorları bulmak için __contains özelliğini kullanacağız.
>>> doktor = Doktor.objects.filter(adi__contains='a')
>>> doktor
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Ali , Yılmaz ,>]
Veri Sıralama
Sıralama işlemini obects.order_by() özelliği ile yapabiliriz.
>>> Doktor.objects.order_by('adi')
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Mahmut , Yılmaz ,>, <Doktor: Veysel , Duran ,veysel@mail.com>]
Doktor tablosunu isme göre sıralamış olduk. Sorgu ise şu şekilde olacaktır.
SELECT *
FROM Doktor
ORDER BY adi;
Eğer ters sıralama yapmak istersek yapmamız gereken tek şey ismin önüne-(eksi) işareti koymak.
>>> Doktor.objects.order_by('-adi')
[<Doktor: Veysel , Duran ,veysel@mail.com>, <Doktor: Mahmut , Yılmaz ,>, <Doktor: Ahmet , Mehmet ,doktor@mail.com>]
Eğer bir tablodan veri çekerken varsayılan olarak bir alana göre sıralanmasını istersek o tabloya ait Modele şu satırları eklememiz gerekir.
class Meta:
    ordering = ['adi']
Modelin son hali şu şekilde olacaktır.
class Polikilinik(models.Model):
 kodu = models.CharField(max_length=20)
 adi = models.CharField(max_length=50)
 doktor = models.ForeignKey(Doktor)


 def __unicode__(self):
  return u'%s , %s ' % (self.kodu,self.adi)

 class Meta:
  ordering = ['adi']
Şimdi sıralama özelliğini kullanmadan tablodan tüm verileri çekelim.
>>> polikilinikler = Polikilinik.objects.all()
>>> polikilinikler
[<Polikilinik: P405 , Adapazarı >, <Polikilinik: P404 , Serdivan >]
Polikilinikler sıralı bir biçimde geldi.
Veri Güncelleme
İlk önce veriyi alıp sonra istediğimiz alanı değiştirebiliriz.
>>> doktor = Doktor.objects.filter(adi='Ali')[0]
>>> doktor.adi = 'Mahmut'
>>> doktor.save()
>>> doktor
<Doktor: Mahmut , Yılmaz ,>
Şu şekilde bir kullanımda yapabiliriz
>>> doktor = Doktor.objects.filter(adi='Mahmut').update(eposta='mahmut@mail.com')
>>> doktor
1
Gördüğünüz gibi bu kullanımda eğer güncelleme başarılı ise geriye 1 başarısız size 0 döner. Güncellemeyi kontrol edelim.
>>> doktor = Doktor.objects.filter(adi='Mahmut')
>>> doktor
[<Doktor: Mahmut , Yılmaz ,mahmut@mail.com>]
Sorgusu şu şekilde olacaktır.
UPDATE Doktor
SET eposta = 'mahmut@mail.com'
WHERE adi='Mahmut'
Veri Dilimleme
Veri güncelleme işlemi yaparken aynı zamanda dilimle işlemi de yapmış olduk. Tablodan veri çekerken birden fazla satır gelebilir. Biz istersek bu gelen satırlardan ilkini ikincisini veya birden ona kadar olan aralığını alabiliriz. İlk satırı alalım.
>>> doktor = Doktor.objects.all()[0]
>>> doktor
<Doktor: Ahmet , Mehmet ,doktor@mail.com<
İkinci satırı alalım.
>>> doktor = Doktor.objects.all()[1]
>>> doktor
<Doktor: Mahmut , Yılmaz ,>
İlk on satırı alalım.
>>> doktor = Doktor.objects.all()[0:10]
Doktor tablosundaki ilk 10 satırı geriye döndürecektir. Sorgusu ise şu şekildedir.
SELECT *
FROM Doktor
OFFSET 0 LIMIT 2;
Doktorlar tablosundan ada göre sıralama yaparak ilk satırı getirebiliriz.
>>> doktor = Doktor.objects.order_by('adi')[0]
>>> doktor
<Doktor: Ahmet , Mehmet ,doktor@mail.com>
Verileri dilimlerken negatif sayılar kullanılmaz.
>>> doktor = Doktor.objects.all()[-1]
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 112, in __getitem__
    "Negative indexing is not supported."
AssertionError: Negative indexing is not supported.
Veri Silme
Nesneleri silmek için delete() metodunu kullanacağız.
>>> doktor_sil = Doktor.objects.filter(adi='Mahmut').delete()
>>> doktorlar = Doktor.objects.all()
>>> doktorlar
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>, <Doktor: Veysel , Duran ,veysel@mail.com>]
Mahmut isimli kullanıcıyı sildik. Doktor tablosundaki tüm satırları silebiliriz.
Doktor.objects.all().delete()
Silme işlemini şu şekilde de yapabiliriz.
>>> doktor_sil = Doktor.objects.get(adi='Veysel')
>>> doktor_sil.delete()
>>> doktorlar
[<Doktor: Ahmet , Mehmet ,doktor@mail.com>]
Veysel isimli dokturu da silmiş olduk.
Diğer model alan tiplerine buradan ulaşabilirsiniz.
Kaynakça