1 from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage
3 class InfinitePaginator(Paginator):
5 Paginator designed for cases when it's not important to know how many total pages.
6 This is useful for any object_list that has no count() method or can be used to
7 improve performance for MySQL by removing counts.
9 The orphans parameter has been removed for simplicity and there's a link template string
10 for creating the links to the next and previous pages.
12 Class name is pronounced verbally in a deep tone.
15 def __init__(self, object_list, per_page, allow_empty_first_page=True, link_template='/page/%d/'):
16 orphans = 0 # no orphans
17 super(InfinitePaginator, self).__init__(object_list, per_page, orphans, allow_empty_first_page)
18 # no count or num pages
19 del self._num_pages, self._count
21 self.link_template = link_template
23 def validate_number(self, number):
24 "Validates the given 1-based page number."
28 raise PageNotAnInteger('That page number is not an integer')
30 raise EmptyPage('That page number is less than 1')
33 def page(self, number):
34 "Returns a Page object for the given 1-based page number."
35 number = self.validate_number(number)
36 bottom = (number - 1) * self.per_page
37 top = bottom + self.per_page
38 page_items = self.object_list[bottom:top]
39 # check moved from validate_number
41 if number == 1 and self.allow_empty_first_page:
44 raise EmptyPage('That page contains no results')
45 return InfinitePage(page_items, number, self)
48 "Returns the total number of objects, across all pages."
49 raise NotImplementedError
50 count = property(_get_count)
52 def _get_num_pages(self):
53 "Returns the total number of pages."
54 raise NotImplementedError
55 num_pages = property(_get_num_pages)
57 def _get_page_range(self):
59 Returns a 1-based range of pages for iterating through within
62 raise NotImplementedError
63 page_range = property(_get_page_range)
65 class InfinitePage(Page):
68 return '<Page %s>' % self.number
71 "Checks for one more item than last on this page."
73 next_item = self.paginator.object_list[self.number * self.paginator.per_page]
80 Returns the 1-based index of the last object on this page,
81 relative to total objects found (hits).
83 return (self.number - 1) * self.paginator.per_page + len(self.object_list)
85 '''Bonus methods for creating links'''
89 return self.paginator.link_template % (self.number + 1)
92 def previous_link(self):
93 if self.has_previous():
94 return self.paginator.link_template % (self.number - 1)