{"id":515,"date":"2017-09-11T13:24:39","date_gmt":"2017-09-11T17:24:39","guid":{"rendered":"https:\/\/dashdrum.com\/blog\/?p=515"},"modified":"2017-09-11T13:24:39","modified_gmt":"2017-09-11T17:24:39","slug":"fun-with-pagination-back-and-ahead-by-5","status":"publish","type":"post","link":"https:\/\/dashdrum.com\/blog\/2017\/09\/fun-with-pagination-back-and-ahead-by-5\/","title":{"rendered":"Fun with Pagination &#8211; Back and Ahead by 5"},"content":{"rendered":"<p>Yesterday I wanted to beef up a ListView-based page with additional navigation controls.\u00a0 Specifically, I decided to add buttons to jump back 5 and ahead 5 pages in the list.\u00a0 With a little bit of class extension, this was easy to do.<\/p>\n<p>Source:<\/p>\n<pre>from django.core.paginator import Page, Paginator\r\n\r\nclass PageFive(Page):class PageFive(Page):\r\n\r\n    ''' Include info for next 5 and previous 5 pages '''\r\n\r\n    def has_next_five(self): \r\n        return self.number &lt; self.paginator.num_pages - 5 \r\n\r\n    def has_previous_five(self): \r\n        return self.number &gt; 6\r\n\r\n    def next_five_page_number(self): \r\n        return self.paginator.validate_number(self.number + 5)\r\n\r\n    def previous_five_page_number(self): \r\n        return self.paginator.validate_number(self.number - 5)\r\n\r\n\r\nclass PaginatorFive(Paginator):\r\n\r\n ''' Uses the PageFive class to report info for next and previous 5 pages\r\n     Set pageinator_class in ListView to use '''\r\n\r\n    def _get_page(self, *args, **kwargs): \r\n        \"\"\" \r\n        Return an instance of a single page using the PageFive object \r\n        \"\"\" \r\n\r\n        return PageFive(*args, **kwargs)<\/pre>\n<p>First step was to extend the <code>Page<\/code>class to add additional methods.\u00a0 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.<\/p>\n<p>To use my new <code>PageFive<\/code>class, I also extended the <code>Paginator<\/code>\u00a0class.\u00a0 Lucky for me, the authors have included the <code>_get_page()<\/code>method as a hook to modify the <code>Page<\/code>class used.\u00a0 Simple to override.<\/p>\n<p>Next, I have to tell <code>ListView<\/code>to call my redefined paginator.\u00a0 The <code>paginator_class<\/code>variable is used to make that change:<\/p>\n<pre>class MyListView(ListView):\r\n    model = MyModel\r\n    paginate_by = 10\r\n    paginator_class = PaginatorFive\r\n\r\n<\/pre>\n<p>Finally, I can use the new methods of the <code>PageFive<\/code>class in the template:<\/p>\n<pre>&lt;!-- PaginatorFive navigation buttons --&gt;\r\n {% if is_paginated %}\r\n   &lt;ul class=\"pagination pagination-centered\"&gt;\r\n     {% if page_obj.has_previous %}\r\n       &lt;li&gt;&lt;a href=\"?page=1\"&gt;First&lt;\/a&gt;&lt;\/li&gt;\r\n       {% if page_obj.has_previous_five %}\r\n         &lt;li&gt;&lt;a href=\"?page={{ page_obj.previous_five_page_number }}\"&gt;Back 5&lt;\/a&gt;&lt;\/li&gt;\r\n       {% endif %}\r\n       &lt;li&gt;&lt;a href=\"?page={{ page_obj.previous_page_number }}\"&gt;Prev&lt;\/a&gt;&lt;\/li&gt;\r\n    {% endif %}\r\n\r\n    &lt;li class=\"active\" &gt;&lt;a href=\"?page={{page_obj.number}}\"&gt;{{page_obj.number}} of{{ page_obj.paginator.num_pages }}&lt;\/a&gt;&lt;\/li&gt;\r\n\r\n    {% if page_obj.has_next %}\r\n       &lt;li&gt;&lt;a href=\"?page={{ page_obj.next_page_number }}\"&gt;Next&lt;\/a&gt;&lt;\/li&gt;\r\n       {% if page_obj.has_next_five %}\r\n         &lt;li&gt;&lt;a href=\"?page={{ page_obj.next_five_page_number }}\"&gt;Ahead 5&lt;\/a&gt;&lt;\/li&gt;\r\n       {% endif %}\r\n       &lt;li&gt;&lt;a href=\"?page={{ page_obj.paginator.num_pages }}\"&gt;Last&lt;\/a&gt;&lt;\/li&gt;\r\n     {% endif %}\r\n   &lt;\/ul&gt;\r\n {% endif %}<\/pre>\n<p>This was a fun little exercise.<\/p>\n<p>&nbsp;<\/p>\n<p>(Sorry for the word wrap in the code.\u00a0 Copy to your editor for a better view)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yesterday I wanted to beef up a ListView-based page with additional navigation controls.\u00a0 Specifically, I decided to add buttons to jump back 5 and ahead 5 pages in the list.\u00a0 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): &#8221;&#8217; Include info for &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/dashdrum.com\/blog\/2017\/09\/fun-with-pagination-back-and-ahead-by-5\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Fun with Pagination &#8211; Back and Ahead by 5&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-515","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/comments?post=515"}],"version-history":[{"count":2,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/515\/revisions"}],"predecessor-version":[{"id":517,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/515\/revisions\/517"}],"wp:attachment":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/media?parent=515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/categories?post=515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/tags?post=515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}