Browse Source

Fix #421: looking ahead paginator

Rafał Pitoń 10 years ago
parent
commit
28d80f64be
2 changed files with 73 additions and 0 deletions
  1. 44 0
      misago/threads/paginator.py
  2. 29 0
      misago/threads/tests/test_paginator.py

+ 44 - 0
misago/threads/paginator.py

@@ -0,0 +1,44 @@
+from django.core.paginator import Paginator as DjangoPaginator, Page, EmptyPage
+from django.http import Http404
+
+
+class Paginator(DjangoPaginator):
+    def page(self, number):
+        """
+        Returns a Page object for the given 1-based page number.
+
+        If its not last page, it will also contain one element of last page
+        """
+        number = self.validate_number(number)
+        bottom = (number - 1) * self.per_page
+        top = bottom + self.per_page
+        if top + self.orphans >= self.count:
+            top = self.count
+        else:
+            top += 1
+        return self._get_page(self.object_list[bottom:top], number, self)
+
+    def _get_page(self, *args, **kwargs):
+        page = Page(*args, **kwargs)
+        if page.has_next():
+           page.next_page_first_item = page[-1]
+           page.object_list = page.object_list[:-1]
+        else:
+           page.next_page_first_item = None
+        return page
+
+
+def paginate(object_list, page, per_page, orphans=0):
+    from misago.core.exceptions import ExplicitFirstPage
+
+    if page in (1, "1"):
+        raise ExplicitFirstPage()
+    elif not page:
+        page = 1
+
+    try:
+        return Paginator(
+            object_list, per_page, orphans=orphans,
+            allow_empty_first_page=allow_empty_first_page).page(page)
+    except EmptyPage:
+        raise Http404()

+ 29 - 0
misago/threads/tests/test_paginator.py

@@ -0,0 +1,29 @@
+from django.test import TestCase
+
+from misago.threads.paginator import Paginator
+
+
+class PaginatorTests(TestCase):
+    def test_paginator_page_orphas(self):
+        """paginator.page() returns orphans"""
+        items = range(10)
+
+        paginator = Paginator(items, 7, orphans=5)
+        page = paginator.page(1)
+
+        self.assertEqual(page.object_list, items)
+        self.assertIsNone(page.next_page_first_item)
+
+    def test_paginator_page_look_ahead(self):
+        """paginator.page() has lookahead"""
+        items = range(10)
+
+        paginator = Paginator(items, 6, orphans=3)
+        page = paginator.page(1)
+
+        self.assertEqual(page.object_list, items[:6])
+        self.assertEqual(page.next_page_first_item, items[6])
+
+        page = paginator.page(2)
+        self.assertEqual(page.object_list, items[6:])
+        self.assertIsNone(page.next_page_first_item)