Django bize sorgu sonuçlarını sayfalandırarak sunma imkanı vermekte. Bunun için django.core.paginator modülünü kullanacağız. Detaylı bilgiye buradan ulaşabilirsiniz. Öncelikle tekrardan kaçınmak için views.py dosyasında pager adında bir fonksiyon yazdım. Bu fonksiyon kendisine verilen sonuç listesini sayfalandırmakta. Her sayfada ise per_page sonuç görüntülemekte. Aşağıda views.py ve şablon dosyasından kısa parçalar görebilirsiniz.
Django lets us paginate our query results via its django.core.paginator module. You can get detailed information here. First of all, I wrote a pager function in order to obey DRY principles. This function paginates the result set and in every page, it displays per_page result. Below you can see parts from views.py and template file.
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from django.core.paginator import Paginator, InvalidPage, EmptyPage def pager(request, entry_list, per_page=LIST_SIZE): """Paginates the given resultset.""" paginator = Paginator(entry_list, per_page) try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 try: entries = paginator.page(page) except (EmptyPage, InvalidPage): entries = paginator.page(paginator.num_pages) return entries def list_package_contents(request, version, package_name): entry_list = Repo.objects.filter(repo = version.replace("-", "_"), package = package_name) return render_to_response('pathsearch/results.html', { 'entries' : pager(request, entry_list), 'result_count' : len(entry_list), }) |
Görüldüğü üzere entry_list veritabanından dönen sonuç listesi. Bunu pager fonksiyonuna sokarak şablon dosyasına gönderiyoruz.
As can be seen, entry_list is the result set from the database. We are sending this data after processing with pager function so that it can be paginated.
results.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | {% blocktrans with entries.start_index as si and entries.end_index as ei%} {{ result_count }} results
Showing results between {{ si }} and {{ ei }}{% endblocktrans %}
{% for entry in entries.object_list %}
<a href="/search/{{current_version}}/package/{{ entry.package }}/">{{ entry.package }}</a>
{{ entry.path }}
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if entries.has_previous %}
<a href="?page=1">{% trans 'First' %}</a> |
<a href="?page={{ entries.previous_page_number }}">{% trans 'Previous' %}</a> |
{% endif %}
<span class="current">
{% blocktrans with entries.number as pn and entries.paginator.num_pages as np%}Page {{ pn }} / {{ np }}{% endblocktrans %}
</span>
{% if entries.has_next %}
| <a href="?page={{ entries.next_page_number }}">{% trans 'Next' %}</a> |
<a href="?page={{ entries.paginator.num_pages }}">{% trans 'Last' %}</a>
{% endif %}
</span></div> |
Değişkenler kendini büyük ölçüde anlatıyor. Kodla çıktıyı karşılaştırarak anlamadığınız noktaları çözebilirsiniz. Çıktıda sonuç aralığı bilgisi, sayfaya ait sonuçlar ve yönelim bağlantıları mevcut.
Variables are mostly self-explaining. So you can compare the code with the output. We have a result range information, results for the page and the navigation links.
Bu yöntemin bir eksiği ise çok sayıda sonuç veren sorguları hızlandırmamakta olması. Sebebi ise önce entry_list’i hesaplayıp sonra onu sayfalandırmamız. Her halükarda koca veriyi bir listeye atmadan sayfalandırma safhası başlamıyor. Darboğaz verinin alınmasında. Bu sebeple tembel sayfalandırma mümkün mü araştırmaktayım.
The drawback of this method is that it can’t speed up the queries with a huge result set. Reason is that we first fetch the result data and put it into entry_list and then paginate it. No matter what, pagination won’t start until the data is completely fetched. The bottleneck is in this phase. So I’m wondering if a lazy pagination is possible.