Django'da Sayfalama - Pagination
Django’da Sayfalama - Pagination¶
Sayfalamaya neden ihtiyaç var ?¶
Verilerin çokluğundan doğan bir ihtihaç sayfalama mantığını getirmiştir, bütün veriler tek bir sayfada olmuş olsaydı
- sayfa geç yüklenir
- kullanıcılar uzun süre beklemek durumun da kalır
- sunucumuz fazla iş yapmış ve yorulmuş olur
- internet’de aynı zaman da fazla dan harcanmış olur
- tasarım açısından da pek hoş görünmez di.
bunların sonucunda ise kullanıcılar web sitelerinde uzun süre kalmaz ve ayrılırlar büyük ihtimalle
Bu yüzden bu gün django’da bulunan \( from django.core.paginator import Paginator \) paginator fonksiyonunu kullanmayı öğreneceğiz.
bence bu fonksiyonu tools.py adında bir dosya açıp paginator adında bir fonksiyon yazın ve gerekli olan bütün yerlerde bu fonksiyonu çağırarak kullanın bu sayede hız kazanmış olursunuz.
Django ile sayfalama \( Pagination \) - Mantığını Anlamak¶
Öncelikle Paginator fonksiyonunu projemize dahil edelim,
from django.core.paginator import Paginator
Objects adında bir liste tanımlayalım objects = ['john', 'paul', 'george', 'ringo']
Şimdi bu listeyi Paginator fonksiyonu yardımı ile sayfalıyalım ve mantığını kavrayalım.
p = Paginator(objects, 2)
p adında bir değişken oluşturduk ve objects listesini birinci argüman olarak Paginator içine attık, Paginator’ un ikinci değişkeni her sayfada kaç tane öğe görünmesini istediğimizi belirler burada 2 yazdığımız için her sayfada sadece 2 öğe görünecektir.
p.count
count ile p içindeki toplam nesne sayısını öğrenebiliriz burada çıktı olarak 4 verecektir.
p.num_pages
num_pages ile p değişkeninde bulunan verileri toplamda kaç sayfada göstereceğimiz bilgisine ulaşabiliriz burada Paginator fonksiyonunun ikinci değişkenine 2 yazdığımız için ve objects nesnesi 4 öğeden oluştuğu için toplam gösterilecek sayfa sayısı 4/2 = 2 dir yanı p.num_pages bize 2 çıktısını verecektir.
p.page(1)
sayfa getirmek istersek page() fonksiyonunu kullanıyoruz bu fonksiyon sadece bir parametre alır oda getirmek istenilen sayfanın sayısıdır, çıktı olarak bize <Page 1 of 2>
bunu verecektir, getirdiğiniz sayfada bulunan verileri almak isterseniz, object_list methodunu kullanmanız gerekir yanı sonuc olarak şöyle yapmanız gerek.
page1 = p.page(1) # <Page 1 of 2>
page1.object_list # ['john', 'paul'] # çıktı olarak bunu verir
page2 = p.page(2)
page2.object_list # ['george', 'ringo'] ikinci sayfadaki veriler
sayfaları tek tek çağırmak yerine sırayla bir sonraki sayfayı çağırmak için has_next() fonksiyonunu kullanmak gerek ,bir önceki sayfayı çağırmak yanı verilerine erişmek için ise has_previous()
bunlar eğer bir sonraki veya bir önceki sayfa mevcut ise True eğer çağrılan sayfalar yok ise False değeri döndürür.
page2.has_next() # False 3. sayfa olmadığı için False
page2.has_previous() # True 2 den bir önceki sayfa yani 1.sayfa oldugu için True
verisi gelen sayfanın ilk verinin numarasını öğrenmek için start_index() , gelen verinin sonundaki veri numarasını öğrenmek için ise end_index() fonksiyonu kullanılır
Örnek¶
page2.start_index() # 3 çıktısını verir çunkü 2. sayfada ki ilk eleman objects listesinin 3. elemanıdır
page2.end_index() # 4 çıktısını verir çunkü 2. sayfada ki son eleman objects listesinin 4. elemanıdır
Peki Bu Bilgileri Template’de Nasıl Kullanacağız ?¶
önce tools.py adında bir dosya oluşturun veya yazmak istediğiniz views.py içine Paginator ve onun hata sınıflarını dahil edelim
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
PageNotAnInteger sınıfı eğer gelen sayfa isteği sayı değil ise bu sınıfı kullanarak hatayı yakalıyabiliyoruz
EmptyPage sınıfı ise gelen sayfa isteği bulunan sayfa sayısı dışında ise bu hatayı yakalamamıza yardım eden sınıftır.
Şimdi paginator adlı fonksiyonumuzu oluşturalım ve başka yerlerde sürekli bunu kullanmak için şekillendirelim.
www.coogger.com sayfalama fonksiyonu şu şekilde bu aynı zamanda django dökümanlarında bulunan kodlardırın biraz değiştirilmiş halidir.
def paginator(request,queryset,hmany=20):
paginator = Paginator(queryset, hmany)
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
return contacts
şimdi 3 tane parametre alıyor birincisi gelen istekler olan request, ikincisi sayfalamak istediğimiz verimiz \( bu veriler veri tabanından aldıgımız verilerdir \) üçüncüsü bir sayfada kaç tane veri görünmesi gerektiği.
try ve except ile hataları yakalıyoruz , eğer gelen sayfa isteği sayı değil ise birinci sayfanın verilerini veriyoruz , eğer gelen sayfa isteği bulunan sayfa sayısı dışında ise son sayfayı veriyoruz.
template’ ımız de şu şekilde olacak
<div class="pagination">
<span class="step-links">
{% if blog.has_previous %}
<a class="step-links-a" href="?page={{ blog.previous_page_number }}">geri</a>
{% endif %}
<span class="current">
{{ blog.number }} | {{ blog.paginator.num_pages }}
</span> {% if blog.has_next %}
<a class="step-links-a" href="?page={{ blog.next_page_number }}">ileri</a> {% endif %}
</span>
</div>
Yükarıda anlattıklarımı kullanarak bunu değiştirebilirsiniz bana sadece bu gerektiği için ben bunu kullandım.
<a class="step-links-a" href="?page
buradaki ?page i kullanarak yeni bir url yapmadan burdaki veriyi
request.GET.get('page')
bu kod ile çekebilirsiniz bizde istenilen sayfa sayısını bu şekilde çektik.
Şimdi bu oluşturduğumuz temayı ve paginator fonksiyonunu kullanalım.
from models import Blog
from views import tools
queryset = Blog.objects.all()
blogs = tools.paginator(request,queryset)
return render(request,"blog/blogs.html",{"blogs":blogs})
burada Blog nesnesinden \( veri tabanından \) bütün verileri çektik çekilen verileri tools.py modulumuzdeki paginator adlı fonksiyonun 2. paremetresine attık ,1 .parametreye gelen istekler olan request i verdik ve sayfamızda 20 tane içerik görünmesini istediğimiz için 3. parametreyi tekrar yazma ihtiyacı duymadık
paginator fonksiyonu bize sayfaladı ve veriyi çıktı olarak verip blogs değişkenine attı bizde onu blogs.html adlı temamıza blogs ismi ile yolladık.
işlem bu kadar arkadaşlar kolay gelsin görüşmek üzere.
Kodların son hali¶
tools.paginator
def paginator(request,queryset,hmany=20):
paginator = Paginator(queryset, hmany)
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
contacts = paginator.page(1)
except EmptyPage:
contacts = paginator.page(paginator.num_pages)
return contacts
blogs.html
{% include 'home/head.html' %} {% include 'home/header.html' %} {% include 'home/nav.html' %} {% if blog %}
<div class="blogs">
<div class="main-blog-cards">
{% include 'blog/blog-cards.html' %}
</div>
</div>
{% include "home/paginator.html" %} {% endif %}
blogs.html içinde paginator.html ı dahil ediyoruz
paginator.html
<div class="pagination">
<span class="step-links">
{% if blog.has_previous %}
<a class="step-links-a" href="?page={{ blog.previous_page_number }}">geri</a>
{% endif %}
<span class="current">
{{ blog.number }} | {{ blog.paginator.num_pages }}
</span> {% if blog.has_next %}
<a class="step-links-a" href="?page={{ blog.next_page_number }}">ileri</a> {% endif %}
</span>
</div>
style.css
.pagination {
position: relative;
width: max-content;
padding: 30px 10px 30px 10px;
margin: auto;
margin-bottom: 60px;
}
.current {
padding: 6px;
border: 1px solid #f1f1f1;
background: rgb(0, 0, 0);
color: #fff;
border-radius: 6px;
margin-right: 14px;
}
.step-links-a {
padding: 6px;
color: #fff;
background: blue;
border: 1px solid #f1f1f1;
border-radius: 6px;
}
Created: April 16, 2024