improve paginator on list.
Should closes bug #14.
--- a/src/p4l/config.py.tmpl Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/config.py.tmpl Tue Dec 03 20:55:04 2013 +0100
@@ -161,6 +161,9 @@
# pagination of the list of record
NB_RECORDS_BY_PAGE = 20
+#some control on the pagination appareance
+PAGINATOR_VISIBLE_RANGE = 5 #number of pages
+PAGINATOR_START_RANGE = 2 #number of pages kept at the beggining and at the end of the range
# url of the sesame repository containing all the rdf referentials
SPARQL_QUERY_ENDPOINT = "http://localhost:8080/openrdf-sesame/repositories/plan4learning"
@@ -172,3 +175,4 @@
'env' : {'PYTHONPATH': '/Users/ymh/dev/venvs/p4l/lib/python2.7/site-packages'}
}
+
--- a/src/p4l/search/views.py Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/search/views.py Tue Dec 03 20:55:04 2013 +0100
@@ -33,11 +33,14 @@
from django.conf import settings
+from django.core.paginator import InvalidPage
+from django.http.response import Http404
from django.template.context import RequestContext
from haystack.query import SearchQuerySet
from haystack.views import SearchView, search_view_factory
from p4l.search.forms import RecordSearchForm
+from p4l.utils import P4lPaginator
class RecordSearchView(SearchView):
@@ -52,3 +55,32 @@
@classmethod
def as_view(cls):
return search_view_factory(view_class=cls)
+
+ def build_page(self):
+ """
+ Paginates the results appropriately.
+
+ In case someone does not want to use Django's built-in pagination, it
+ should be a simple matter to override this method to do what they would
+ like.
+ """
+ try:
+ page_no = int(self.request.GET.get('page', 1))
+ except (TypeError, ValueError):
+ raise Http404("Not a valid number for page.")
+
+ if page_no < 1:
+ raise Http404("Pages should be 1 or greater.")
+
+ start_offset = (page_no - 1) * self.results_per_page
+ self.results[start_offset:start_offset + self.results_per_page]
+
+ paginator = P4lPaginator(self.results, self.results_per_page)
+
+ try:
+ page = paginator.page(page_no)
+ except InvalidPage:
+ raise Http404("No such page!")
+
+ return (paginator, page)
+
--- a/src/p4l/settings.py Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/settings.py Tue Dec 03 20:55:04 2013 +0100
@@ -212,6 +212,10 @@
}
NB_RECORDS_BY_PAGE = 20
+#some control on the pagination appareance
+PAGINATOR_VISIBLE_RANGE = 5 #number of visible pages
+PAGINATOR_START_RANGE = 2 #number of pages kept at the beggining and at the end of the range
+
HAYSTACK_CONNECTIONS = {
'default': {
@@ -285,6 +289,7 @@
SCRIPT_WAIT = .250
SCRIPT_MAX_WAIT = 40 # * SCRIPT_WAIT = 10 sec
+
from config import * # @UnusedWildImport
if not "SRC_BASE_URL" in locals():
--- a/src/p4l/templates/p4l/home.html Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/templates/p4l/home.html Tue Dec 03 20:55:04 2013 +0100
@@ -25,19 +25,23 @@
</form>
</div>
</div>
- <div class="pagination pull-right">
- {% if page.has_previous or page.has_next %}
- <span class="page-links">
- {% if page.has_previous %}
- <a href="?page={{ page.previous_page_number }}&q={{query}}">{% trans 'Previous' %}</a>
+<div class="pagination pull-right">
+ {% if page.has_previous or page.has_next %}
+ <ul class="pagination">
+ <li class="{% if page.number == 1 %}disabled{% endif %}"><a {% if page.number != 1 %}href="?page=1&q={{query}}"{% endif %}><<</a></li>
+ <li class="{% if not page.has_previous %}disabled{% endif %}"><a {% if page.has_previous %}href="?page={{ page.previous_page_number }}&q={{query}}"{% endif %}><</a></li>
+ {% for p in page.visible_page_range %}
+ {% if p == 0 %}
+ <li class="disabled"><a>…</a></li>
+ {% elif p == page.number %}
+ <li class="active"><a>{{ page.number }}</a></li>
+ {% else %}
+ <li><a href="?page={{ p }}&q={{query}}">{{ p }}</a></li>
{% endif %}
- <span class="page-current">
- {% trans 'Page' %} {{ page.number }} {% trans 'on' %} {{ paginator.num_pages }}
- </span>
- {% if page.has_next %}
- <a href="?page={{ page.next_page_number }}&q={{query}}">{% trans 'Next' %}</a>
- {% endif %}
- </span>
+ {% endfor %}
+ <li class="{% if not page.has_next %}disabled{% endif %}"><a {% if page.has_next %}href="?page={{ page.next_page_number }}&q={{query}}"{% endif %}>></a></li>
+ <li class="{% if not page.has_next or page.number == paginator.num_pages %}disabled{% endif %}"><a {% if page.has_next and page.number != paginator.num_pages %}href="?page={{ paginator.num_pages }}&q={{query}}"{% endif %} >>></a></li>
+ </ul>
{% else %}
<span> </span>
{% endif %}
--- a/src/p4l/utils.py Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/utils.py Tue Dec 03 20:55:04 2013 +0100
@@ -32,13 +32,14 @@
#
import codecs
+import hashlib
import logging
import math
-import hashlib
import sys
import unicodedata
from django.conf import settings
+from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage, Page
from django.core.validators import URLValidator
from django.utils.http import urlquote_plus
import requests
@@ -246,4 +247,55 @@
return hashlib.md5(value).hexdigest()
+class P4lPaginator(Paginator):
+
+ def validate_number(self, number):
+ "Validates the given 1-based page number."
+ try:
+ number = int(number)
+ except (TypeError, ValueError):
+ raise PageNotAnInteger('That page number is not an integer')
+ if number < 1:
+ return 1
+ if number > self.num_pages:
+ if number == 1 and self.allow_empty_first_page:
+ return 1
+ elif self.num_pages > 0:
+ return self.num_pages
+ else:
+ raise EmptyPage('That page contains no results')
+ return number
+
+
+ def page(self, number):
+ page = super(P4lPaginator, self).page(number)
+ return P4lPage(page.object_list, page.number, self)
+
+
+class P4lPage(Page):
+
+ visible_range = getattr(settings, 'PAGINATOR_VISIBLE_RANGE', 5)
+ start_range = getattr(settings, 'PAGINATOR_START_RANGE', visible_range/2)
+
+ def __get_start_range(self):
+ return max(1,self.number-self.visible_range/2)
+
+ def __get_end_range(self):
+ return min(self.paginator.num_pages, self.number+self.visible_range/2) + 1
+
+ def visible_page_range(self):
+ start = self.__get_start_range()
+ end = self.__get_end_range()
+
+ ranges = set(range(1,self.start_range+1)) | set(range(start , end)) | set(range(self.paginator.num_pages - self.start_range +1, self.paginator.num_pages+1))
+ prev = None
+ res = []
+ for i in sorted(ranges):
+ if 1 <= i <= self.paginator.num_pages:
+ if prev and i-prev > 1:
+ res.append(0)
+ res.append(i)
+ prev = i
+ return res
+
\ No newline at end of file
--- a/src/p4l/views.py Tue Dec 03 13:54:30 2013 +0100
+++ b/src/p4l/views.py Tue Dec 03 20:55:04 2013 +0100
@@ -149,7 +149,7 @@
context['languages_list'] = json.dumps(settings.LANGUAGES_LIST)
context['is_create_view'] = json.dumps(self.is_create_view)
-
+
return context