Yesterday I wanted to beef up a ListView-based page with additional navigation controls. Specifically, I decided to add buttons to jump back 5 and ahead 5 pages in the list. With a little bit of class extension, this was easy to do.
Source:
from django.core.paginator import Page, Paginator class PageFive(Page):class PageFive(Page): ''' Include info for next 5 and previous 5 pages ''' def has_next_five(self): return self.number < self.paginator.num_pages - 5 def has_previous_five(self): return self.number > 6 def next_five_page_number(self): return self.paginator.validate_number(self.number + 5) def previous_five_page_number(self): return self.paginator.validate_number(self.number - 5) class PaginatorFive(Paginator): ''' Uses the PageFive class to report info for next and previous 5 pages Set pageinator_class in ListView to use ''' def _get_page(self, *args, **kwargs): """ Return an instance of a single page using the PageFive object """ return PageFive(*args, **kwargs)
First step was to extend the Page
class to add additional methods. Mimicking the existing methods for next and previous pages, these four new functions return information on the previous five and next five pages of the list.
To use my new PageFive
class, I also extended the Paginator
class. Lucky for me, the authors have included the _get_page()
method as a hook to modify the Page
class used. Simple to override.
Next, I have to tell ListView
to call my redefined paginator. The paginator_class
variable is used to make that change:
class MyListView(ListView): model = MyModel paginate_by = 10 paginator_class = PaginatorFive
Finally, I can use the new methods of the PageFive
class in the template:
<!-- PaginatorFive navigation buttons --> {% if is_paginated %} <ul class="pagination pagination-centered"> {% if page_obj.has_previous %} <li><a href="?page=1">First</a></li> {% if page_obj.has_previous_five %} <li><a href="?page={{ page_obj.previous_five_page_number }}">Back 5</a></li> {% endif %} <li><a href="?page={{ page_obj.previous_page_number }}">Prev</a></li> {% endif %} <li class="active" ><a href="?page={{page_obj.number}}">{{page_obj.number}} of{{ page_obj.paginator.num_pages }}</a></li> {% if page_obj.has_next %} <li><a href="?page={{ page_obj.next_page_number }}">Next</a></li> {% if page_obj.has_next_five %} <li><a href="?page={{ page_obj.next_five_page_number }}">Ahead 5</a></li> {% endif %} <li><a href="?page={{ page_obj.paginator.num_pages }}">Last</a></li> {% endif %} </ul> {% endif %}
This was a fun little exercise.
(Sorry for the word wrap in the code. Copy to your editor for a better view)