26 Nisan 2014 Cumartesi

Django'da Sayfalama (Pagination)


Merhaba Arkadaşlar,

Bu hafta sizlere Django'da sayfalama (pagination) hakkında bilgi vermek istiyorum. Bildiğiniz üzere web sitelerinde sayfalama genel olarak içeriğin uzun olduğu durumlarda kullanıcıya daha kullanabilir sayfalar üretmek için içeriğin belli mantıksal kısımlara ayrılmasıdır. Genelde arama sonuç sayfalarında, günlük(blog) sitelerinde, uzun içeriğe sahip makalelerde uygulamalarına rastlarız.


Sayfalama alanları genel olarak sitede gezinme alanlarının (navigation) bir parçasıdır. Sitedeki kullanılabilirliği ve düzeni sağlayan normal menü yapılarının dışındaki yapılardır. Sayfalama yaparken aşırıya kaçıp görünüşü çok hoş olsun diye kullanıcıyı zora sokan tasarımlardan kaçınmak gerekir. Sayfalamada önemli olan kullanıcı dostu ve işlevsel bir yapı oluşturmaktır, ondan sonra görsellik gelir. Elbette işlevselliği kaybetmeden görsellikde geliştirilebilir. 
Google sayfalama

Yandex sayfalama



Şimdi Django'nun sayfalamayı nasıl yaptığına bakabiliriz. Öncelikle Django'da sayfalama'yı anlamak için Django kabuğunda küçük bir örnek yapalım. 

>>> from django.core.paginator import Paginator

>>> padisahlar = ['I.Osman','I.Orhan','I.Murat','I.Bayezid','I.Mehmed','II.Murad
','II.Mehmet','II.Bayezid','I.Selim','I.Süleyman','II.Selim','III.Murad','III.Me
hmed']

# Her sayfada üç padişah bulunacak şekilde sayfalayalım :
>>> sayfalar = Paginator(padisahlar,3)

# Tüm sayfalarda bulunan toplam eleman sayısı :
>>> sayfalar.count
13

# Toplam sayfa sayısı
>>> sayfalar.num_pages
5

# İlk sayfa
>>> sayfa1 = sayfalar.page(1)
>>> sayfa1
<Page 1 of 5>

# İlk sayfada bulunan elemanların listesi
>>> sayfa1.object_list
['I.Osman', 'I.Orhan', 'I.Murat']

# Bu sayfadan sonra bir sayfa var mı?
>>> sayfa1.has_next()
True

# Bu sayfadan önce bir sayfa var mı?
>>> sayfa1.has_previous()
False

# Son sayfa
>>> sayfa5 = sayfalar.page(5)
>>> sayfa5
<Page 5 of 5>

# Bu sayfadan sonra bir sayfa var mı?
>>> sayfa5.has_next()
False

# Bu sayfadan önce bir sayfa var mı?
>>> sayfa5.has_previous()
True

# İlk sayfadaki son elemanın indisi
>>> sayfa1.end_index()
3 

# Sayfalama 1'den başlar 
>>> sayfalar.page(0)
Traceback (most recent call last):
 ...
EmptyPage: That page number is less than 1

# Var olmayan bir sayfa çağrıldığında hata yükselir 
>>> sayfalar.page(6)
Traceback (most recent call last):
 ...
EmptyPage: That page contains no results


SAYFALAMANIN GÖRÜNÜMLERDE KULLANILMASI


Sayfalamanın görünümlerde nasıl kullanıldığını bir örnek ile anlatmak istiyorum. Bu yüzden geçen hafatlarda üzerinde çalıştığımız okul projesinde öğretim elemanları listesindeki öğretim elemanlarını sayfalayalım. Geçen hafta Bootstrap konusunu anlattıktan sonra daha güzel bir görünüm elde etmek için şablonumu değiştirdim, sizler de eğer bu örnekten devam ediyorsanız, şablon aşağıdaki gibidir  : 

                                                                                             <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN">
<html>
<head>
    <link rel="stylesheet" type="text/css" href="css/bootstrap.css"/>
    <title> Öğretim Elemanları Listesi </title>
</head>
<body>                                                                                                    
{% load bootstrap3 %}

{% bootstrap_css %}                                                                                        
{% bootstrap_javascript %}

{% bootstrap_messages %}




<div class="panel panel-success">

    <div class ="panel-heading"> <h1> Öğretim Elemanları Listesi </h1></div>
    

    <table class="table table-bordered table-hover" width="500" >
    
        <thead>
            <tr> 
            <th> Sıra</th>
            <th><a href="?sirala=1">Adı</a></th>
            <th><a href="?sirala=2">Soyadı</a></th>
            <th>Telefonu </th>
            <th><a href="?sirala=3">E-posta adresi </a></th> 
            </tr>
        </thead>

        <tbody>
            {% for ogr in ogretim_elemanlari %}
            <tr>
                <td><a href = "/ogretim-elemani-ekleme/?id={{ogr.id}}">{{ogretim_elemanlari                  . start_index|add:forloop.counter0}} </a></td>
                <td><a href="/ogretim-elemani-ekleme/?id={{ogr.id}}">{{ogr.adi}}</a></td>
                <td><a href="/ogretim-elemani-ekleme/?id={{ogr.id}}">{{ogr.soyadi}}</a></td>
                <td>{{ogr.telefonu}}</td>
                <td>{{ogr.e_posta_adresi}}</td>

            </tr>

            {% endfor %}
        </tbody>
    </table>

</div>

        <p><a href = "/ogretim-elemani-ekleme/"> Yeni Kayit</a></p>
    </body>
</html>


ogretim_elemanlari_listesi.html şablonunda  Yeni Kayit köprüsünün hemen üstüne aşağıdaki satırları ekleyerek şablonumuza sayfalamayı uygulamış oluruz. 
        <ul class="pagination pagination-centered">                                              
            {% if ogretim_elemanlari.has_previous %}
                 <li class="active"><a href="?sayfa={{ogretim_elemanlari                                                               .previous_page_number}}">Önceki</a></li>
            {% endif %}
            
            {% for s in ogretim_elemanlari.paginator.page_range %}
             <li><a href ="?sayfa={{s}}">{{s}}  </a></li>
            {% endfor %}
            
            {% if ogretim_elemanlari.has_next %}
                 <li class="active"><a href="?sayfa={{ogretim_elemanlari                                            .next_page_number}}">  Sonraki</a></li>
            {% endif %}                                                                                      
        </ul>


Gördüğünüz gibi sayfalama barını iki koşul için  kontrol ediyoruz. 
  1. Bulunduğumuz sayfadan önce herhangi bir sayfa yoksa
  2. Bulunduğumuz sayfadan sonra herhangi bir sayfa yoksa
Bu işlemi yaptıktan sonra öğretim elemanlarını her sayfada 5 kişi olacak şekilde sayfalayalım. Django'nun sayfalama modülünü kullanabilmek için views.py dosyasının başına  aşağıdaki satırı ekleyelim                                                           
                                  from django.core.paginator import Paginator
Ardından ogretim_elemani_listesi(request)  görünümümüzü şu eklemeleri yapalım :
okul\yonetim\views.py\..ogretim_elemani_listesi(request)..  
...
def ogretim_elemanlari_listesi(request):
    siralama='soyadi'
    olcut = request.GET.get('sirala')                                                                     
    sayfa = request.GET.get('sayfa',1)                                                                   
    if olcut :
        siralamaOlcutleri={
            '1':'adi',
            '2':'soyadi',
            '3':'e_posta_adresi'
            
            }
        if olcut in siralamaOlcutleri:
            siralama = siralamaOlcutleri[olcut]
            
    ogretim_elemanlari_tumu = OgretimElemani.objects.order_by(siralama)                                      
    ogretim_elemanlari_sayfalari = Paginator(ogretim_elemanlari_tumu,5)
    ogretim_elemanlari = ogretim_elemanlari_sayfalari.page(int(sayfa))                               
    return render_to_response('ogretim_elemanlari_listesi.html',locals())

...

Yukardaki görünümümüzden de anlayacağınız gibi sayfalama artık çok basit. Yukarda yaptığımız işlemlerden sonra öğretim elemanları listesi web tarayıcımızda şöyle görüntülenecektir: 

İlk sayfa görüntüsü



Son sayfanın görüntüsü
Tabi bu görüntü listenizde bulunan öğretim görevlisi sayısına göre değişecektir. İyi eğlenceler :)

Hiç yorum yok:

Yorum Gönder