4 Mart 2014 Salı

Şablonların Görünümler ile Kullanılması

Şablonların ne olduğuna ve nasıl kullanıldığından bahsettik. Şuana kadar öğrendiklerimizin hepsi şablonları görünümler ile kullanmak içindi. Küçük bir örnek ile şablonların görünümler ile nasıl kullanıldığına bakalım.
def uni(request):
 s = Template('
{{ uni }} Üniversitesi
') b = Context({'uni':'Sakarya'}) html = s.render(b) return HttpResponse(html)
Bu şekilde çok basit bir örnek ile fikir edinebiliriz. Şimdi bu örneği biraz daha geliştirelim. Üniversitelerin bir kaç özelliğini daha ekleyerek bunu kullanıcıya gösterelim.
İlk önce yapmamız gereken url listesine adresimizi eklemek.
###urls.py###
url(r'^universite/',views.universite)
Şimdi views.py dosyamıza üniversite görünüm işlevini yazalım. İlk önce şablon(template) ve bağlam(context) nesneleri için şu iki satırı ekliyoruz.
###views.py###
from django.http import *
from django.template import Template,Context
Sıra geldi görünüm işlevini tanımlamaya.
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 s = Template(u'''
<table border="1">
 <tr>
  <th>Adı</th><th>Şehir</th><th>Fakülte Sayısı</th><th>Öğrenci Sayısı</th>
 </tr>
 {% for uni in universiteler %}
  <tr>
   <td>{{uni.0}}</td>
   <td>{{uni.1}}</td>
   <td>{{uni.2}}</td>
   <td>{{uni.3}}</td>
  </tr>
 {% endfor %}
</table>
 ''')
 b = Context({'universiteler':universiteler})
 html = s.render(b)
 return HttpResponse(html)
Tanımlamamızı da yaptıktan sonra yapmamız gerekenleri biliyorsunuz. İlk önce Django web sunucusunu çalıştıracağız ve ardından tarayıcıda sayfamıza ulaşabiliriz.
###web sunucusunu çalıştıran kod
python manage.py runserver
###tarayıcıda adres çubuğuna yazmamız gereken adres
http://localhost:8000/universite
Tarayıcıda şu şekilde bir çıktı alacağız.
Sizin de aklınızdan "EE böyle yapacaksam ne anlamı kaldı ki ?" gibi bir cümle geçtiğini tahmin edebiliyoruz. Şablonları böyle kullanmanın bir anlamı yoktur. Daha önce de söylediğimiz gibi şablonların amacı yazılımcı ve tasarımcının işlerinin birbirinden ayırmaktır. Bu şekilde bir kullanımda bu pek mümkün değildir. Bu yüzden şablonları ayrı bir dosya içerisine yazacağız.
Şablonu aşağıdaki gibi yazarak universiteler.html adında kaydediyoruz.
<!DOCTYPE html>
<html>
<head>
 <title>Üniversiteler</title>
</head>
<body>
<table border="1">
 <tr>
  <th>Adı</th><th>Şehir</th><th>Fakülte Sayısı</th><th>Öğrenci Sayısı</th>
 </tr>
 {% for uni in universiteler %}
  <tr>
   <td>{{uni.0}}</td>
   <td>{{uni.1}}</td>
   <td>{{uni.2}}</td>
   <td>{{uni.3}}</td>
  </tr>
 {% endfor %}
</table>

</body>
</html>
Artık views.py dosyasındaki universite görünümünü şu şekilde değiştirebiliriz.
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 s = Template(open('/home/mazlumagar/Django/uygulama/uygulama/sablonlar/universiteler.html').read())
 b = Context({'universiteler':universiteler})
 html = s.render(b)
 return HttpResponse(html)
Template fonksiyonu içerisinde universite.html dosyamızın yolunu belirttik. Sayfamızın çıktısında herhangi bir değişiklik olmadı. İşte bu şekilde html dosyasını ve python dosyasını birbirinden ayırmış olduk. Bu da demek oluyor ki tasarımcı ve programcı birbirinin işlerinden anlamak zorunda değiller.
Template() fonksiyonu içerisine her zaman dosyanın yolunu uzun bir şekilde yazmak zahmetli olacaktır. Bundan kurtulmak için settings.py dosyası içerisinde TEMPLATE_DIRS değişkenine şablonlarımızı kaydettiğimiz dosyanın yolunu göstermeliyiz.
Projemizdeki settings.py dosyasına aşağıdaki kodu ekliyoruz. Tabi ki sizin yolunuz ne ise o şekilde değiştirmelisiniz.
TEMPLATE_DIRS = (
 '/home/mazlumagar/Django/uygulama/uygulama/sablonlar/',
 )
Artık görünüm fonksiyonumuza şablonun yolunu uzun bir şekilde yazmak zorunda değiliz. Bunun için views.py dosyası içerisine get_template fonksiyonunu dahil etmeliyiz.
###views.py dosyasına bu satırı ekliyoruz.
from django.template.loader import get_template
Artık fonksiyonu kullanabiliriz. universite görünümümüzü şu şekilde değiştirebiliriz:
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 s = get_template('universiteler.html')
 b = Context({'universiteler':universiteler})
 html = s.render(b)
 return HttpResponse(htm
TEMPLATE_DIRS değişkenin değerini değiştirmiştik. Değer olarak direk projemizin yolunu atadık. Bu şekilde bir kullanımda projemizin yerini değiştirdiğimiz zaman TEMPLATE_DIRS değişkenin de değerini değiştirmemiz gerekir. Eğer unutursak hata ile karşılaşırız. Projemizin yolunu doğrudan Python kodları ile belirterek işimizi garanti altına alabiliriz.
###TEMPLATE_DIRS değişkenin son hali
TEMPLATE_DIRS = (
 os.path.join(os.path.dirname(__file__),'sablonlar')
 )
sablonlar projemiz altında şablonlarımızı kaydetmek için oluşturduğumuz klasörün adıdır. Eğer windows kullanıyorsanız ve bu kullanım hata veriyorsa. Şu şekilde kullanabilirsiniz.
TEMPLATE_DIRS = (
 os.path.join(os.path.dirname(__file__),'sablonlar').replace('\\','/')
 )

Django'nun bize sağlamış olduğu bazı kolaylıklardan bahsedelim.
render()
Şimdiye kadar hep şu şekilde bir kullanım yaptık.
s = get_template('universiteler.html')
b = Context({'universiteler':universiteler})
html = s.render(b)
İşlemleri sırası ile yapıyoruz. Şablonu içerip veriyi bağlam haline getirdikten sonra şablon içerisine gönderiyorduk. İşte Django bu işlemi daha kısa yoldan yapabilmemiz için bize olanaklar veriyor. render() fonksiyonu işimizi epey kolaylaştıracak. universite görünümümüz içerisinde render() fonksiyonunu kullanalım.
##render() fonksiyonunu içe aktarıyoruz
from django.shortcuts import render
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 return render(request,'universiteler.html',{'universiteler':universiteler})
4 satırda yaptığımız işlemi tek satıra düşürmüş olduk.
render_to_response()
render() fonksiyonu ile aynı işlevi yerine getirir. Farkı request parametresini içermemesidir.
##render_to_response()fonksiyonunu içe aktarıyoruz
from django.shortcuts import render_to_response()
return render_to_response('universiteler.html',{'universiteler':universiteler})
locals()
Bizim için kolaylık sağlayan bir diğer fonksiyon ise local() fonksiyonudur. local() fonksiyonunu şöyle açıklamaya çalışalım, universite() görünümünde şablona veri gönderirken şu kullanımdan yararlandık.
b= Context({"universiteler":universiteler})
Anahtar ve değer ikilisinin de ismi aynı. Tabi gönderdiğimiz bir liste ama biz sadece ismi ile ilgileniyoruz. Projelerimizde de genelde kullanırken isimler aynı oluyor. İşte bu şekilde gönderirken local() fonksiyonu yaptığımız işlemin aynısını bizim için yapıyor. Yani fonksiyonda tanımladığımız tüm değişkenleri anahtar-değer isimleri aynı olacak şekilde yakalıyor ve şablon içerisine gönderiyor.
Üniversiteler görünümümüze başlık adında bir değişken ekleyelim. Ardında local() fonksiyonunu kullanarak değişkenlerimizi kullanalım.
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 baslik = "Üniversiteler Bilgilendirme"
 return render_to_response('universiteler.html',locals())
Artık universiteler.html içerisinde {{ baslik }} şeklinde başlık değişkenini kullanabiliriz. Burada locals() fonksiyonun yaptığı işlem tam olarak şudur.
return render_to_response('universiteler.html',{"universiteler":universiteler,"baslik":baslik})
Şamblonları İçe Aktarmak
Bir proje geliştirirken projenin tamamını tek şablon üzerinden hazırlamak neredeyse imkansızdır. Tek bir şablon üzerinden gitmeye çalışmak hem yeterince zor olacak hem de prejenin büyüdükçe karmaşık bir hal almasına sebep olacaktır. Bu yüzden proje geliştirirken sayfanın görünümlerini farklı şablonlar içerisinde düzenleyerek ana şablon içerine aktarmak çok daha yararlıdır.
Örnek vermek gerekirse bir blog sitesi düşünürsek sayfanın üst kısmı (header) alt kısmı (footer) ve sağ kısmı sürekli sabittir ve sadece içerik kısmı değişmektedir. Bu sabit kısımları farklı şablon dosyaları içerisinde hazırlaya biliriz.
Üniversite örneğimiz üzerinden bu dediklerimizi açıklamaya çalışalım.
home/mazlumagar/Django/uygulama/uygulama/sablonlar/includes/ust_kisim.html
<!DOCTYPE html>
<html>
<head>
 <title>{{ baslik }}</title>
</head>
<body>

<div style="border:2px solid #ddd;padding:10px;margin-bottom:10px">
 Bursa proejmizin üst kısmıdır.
</div>
home/mazlumagar/Django/uygulama/uygulama/sablonlar/includes/alt_kisim.html
<div style="border:2px solid #ddd;padding:10px;margin-top:20px">
Burası sitemizin alt kısmıdır.
</div>

</body>
</html>
universiteler.html dosyası içerisinde ust ve alt kısımları include ifadesini kullanarak içe aktaracağız. home/mazlumagar/Django/uygulama/uygulama/sablonlar/universiteler.html
{% include "includes/ust_kisim.html" %}

<table border="1">
 <tr>
  <th>Adı</th><th>Şehir</th><th>Fakülte Sayısı</th><th>Öğrenci Sayısı</th>
 </tr>
 {% for uni in universiteler %}
  <tr>
   <td>{{uni.0}}</td>
   <td>{{uni.1}}</td>
   <td>{{uni.2}}</td>
   <td>{{uni.3}}</td>
  </tr>
 {%endfor}
</table>

{% include "includes/alt_kisim.html" %}
Eğer tarayıcı da adres çubuğuna http://localhost:8000/universite yazarsanız şu şekilde bir çıktı alacaksınız.

Şablonlarda Kalıtım
Şablonlar içerisinde kalıtım almak mümkündür. Daha öncede bahsettiğimiz gibi bir web sitesinde sadece içerik kısmı değişir. Geri kalan kısımları aynıdır. Yani sitenin bir iskeleti vardır. İşte biz iskeletini bir şablon içerisinde oluşturarak. Oluşturacağımız diğer şablonları buradan kalıtım ile üretebiliriz. Kalıtım kullanırken
{% block blok_adi %} {% endblock %}
ifadelerini kullanacağız. Bu ifadeler kalıtım aldığı sanıfta kullanıldığı yerler ile yer değiştirecektir. Yani kalıtım alan şablon ile kalıtım ile türetilen şablon içerisindeki aynı bloklar yer değiştirir. Eğer ikisinde aynı blok ifadesi kullanılmamış ise bulunduğu şablonda ki haliyle kullanılır. Dediklerimizi örnek ile açıkladığımız zaman daha iyi anlaşılacaktır.
iskelet.html Bu şablondan kalıtım alacağız.
<DOCTYPE html>
<html>
<head>
    <title>{% block sayfa_baslik %}{% endblock %}</title>
<head>
<body>

     {% block ust %}
     {% endblock %}

    <h1>{% block baslik %}{% endblock %}</h1>
    {% block icerik %}{% endblock %}

     
    {% block alt %}
        <div style="border: 2px solid #ddd;padding: 10px;margin-top:20px">
        Burası projemizin alt kısmını içermektedir.
        </div>
    {% endblock %}
</body>
</html>
universiteler2.html Bu şablon iskelet.html'den kalıtım alacak.
{% extends "iskelet.html" %}

    {% block sayfa_baslik %}Üniversiteler{% endblock%}

    {% block ust %}
        <div style="border: 2px solid #ddd;padding: 10px; margin-bottom: 20px">
        Burası projemizin üst kısmıdır
        </div>
    {% endblock %}

    {% block icerik %}
        <table border="1">
            <tr><th>Adı</th><th>Şehir</th><th>Fakülte Sayısı</th><th>Öğrenci Sayısı</th></tr>
            {% for uni in universiteler %}
            <tr><td>{{ uni.0 }}</td><td>{{ uni.1 }}</td><td>{{ uni.2 }}</td><td>{{ uni.3 }}</td></tr>
            {% endfor %}
        </table>
    {% endblock %}
view.spy içersindeki görünüm fonksiyonu
def universite(request):
 universiteler = (
     ['Sakarya','Sakarya',13,70000,],
    ['Yıldız Teknik','İstanbul',10,30000],
    ['Anadolu','Eskişehir',17,22000],
 )
 baslik = "Universiteler Nerde"
 return render_to_response('universiteler2.html',locals())
http://localhost:8000/universite diyerek sayfaya baktığımız zaman çıktımız şu şekilde olacak.
Şimdi birde sayfa kaynağına bakalım.
Gördüğünüz gibi iskelet.html ve universiteler2.html şablonları birleştirildi gibi düşünebiliriz. Eğer aynı blok etiketi ikisinde de varsa kalıtım alan yani universiteler2.html'deki kullanılır. Eğer blok etiketi sadece birinde varsa universiteler2.html içerisinde bulunacaktır.
Kaynakça

3 yorum :

  1. arkadaş ben diyorum neden çalışmıyor örnek. table yerine tabel yazmışsınız. kodlarda rastladım birkaç kelime hatasına. :))
    eline emeğine sağlık. güzel bir kaynak. ve konu başlıklarındaki diğer linklerinde açılmasını sabırsızlıkla bekliyoruz.
    tekrar teşekkürler hocam

    YanıtlaSil
  2. http://hizliresim.com/nPjyl1

    bu satırda hata var diyor lakin yaptıklarınızın aynısını yaptım yol vs. kendime göre ayarladım niye acaba bu hata ?

    YanıtlaSil
  3. Hata views'ı bulamamaktan kaynaklanıyor. urls.py dosyasının başına şu satırı yazarsanız düzelecektir.
    from [uygulama-adi] import views

    YanıtlaSil