mirror of https://github.com/django/django.git
Paginator._get_page hook
This allows for Paginator subclasses to easily override the Page class that gets used. Took the opportunity to also do some non-invasive PEP8 tidying of the paginator module.
This commit is contained in:
parent
8fdb28219d
commit
fbfa654a15
|
@ -7,14 +7,19 @@ from django.utils import six
|
||||||
class InvalidPage(Exception):
|
class InvalidPage(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PageNotAnInteger(InvalidPage):
|
class PageNotAnInteger(InvalidPage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EmptyPage(InvalidPage):
|
class EmptyPage(InvalidPage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Paginator(object):
|
class Paginator(object):
|
||||||
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
|
|
||||||
|
def __init__(self, object_list, per_page, orphans=0,
|
||||||
|
allow_empty_first_page=True):
|
||||||
self.object_list = object_list
|
self.object_list = object_list
|
||||||
self.per_page = int(per_page)
|
self.per_page = int(per_page)
|
||||||
self.orphans = int(orphans)
|
self.orphans = int(orphans)
|
||||||
|
@ -22,7 +27,9 @@ class Paginator(object):
|
||||||
self._num_pages = self._count = None
|
self._num_pages = self._count = None
|
||||||
|
|
||||||
def validate_number(self, number):
|
def validate_number(self, number):
|
||||||
"Validates the given 1-based page number."
|
"""
|
||||||
|
Validates the given 1-based page number.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
number = int(number)
|
number = int(number)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
|
@ -37,16 +44,29 @@ class Paginator(object):
|
||||||
return number
|
return number
|
||||||
|
|
||||||
def page(self, number):
|
def page(self, number):
|
||||||
"Returns a Page object for the given 1-based page number."
|
"""
|
||||||
|
Returns a Page object for the given 1-based page number.
|
||||||
|
"""
|
||||||
number = self.validate_number(number)
|
number = self.validate_number(number)
|
||||||
bottom = (number - 1) * self.per_page
|
bottom = (number - 1) * self.per_page
|
||||||
top = bottom + self.per_page
|
top = bottom + self.per_page
|
||||||
if top + self.orphans >= self.count:
|
if top + self.orphans >= self.count:
|
||||||
top = self.count
|
top = self.count
|
||||||
return Page(self.object_list[bottom:top], number, self)
|
return self._get_page(self.object_list[bottom:top], number, self)
|
||||||
|
|
||||||
|
def _get_page(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns an instance of a single page.
|
||||||
|
|
||||||
|
This hook can be used by subclasses to use an alternative to the
|
||||||
|
standard :cls:`Page` object.
|
||||||
|
"""
|
||||||
|
return Page(*args, **kwargs)
|
||||||
|
|
||||||
def _get_count(self):
|
def _get_count(self):
|
||||||
"Returns the total number of objects, across all pages."
|
"""
|
||||||
|
Returns the total number of objects, across all pages.
|
||||||
|
"""
|
||||||
if self._count is None:
|
if self._count is None:
|
||||||
try:
|
try:
|
||||||
self._count = self.object_list.count()
|
self._count = self.object_list.count()
|
||||||
|
@ -59,7 +79,9 @@ class Paginator(object):
|
||||||
count = property(_get_count)
|
count = property(_get_count)
|
||||||
|
|
||||||
def _get_num_pages(self):
|
def _get_num_pages(self):
|
||||||
"Returns the total number of pages."
|
"""
|
||||||
|
Returns the total number of pages.
|
||||||
|
"""
|
||||||
if self._num_pages is None:
|
if self._num_pages is None:
|
||||||
if self.count == 0 and not self.allow_empty_first_page:
|
if self.count == 0 and not self.allow_empty_first_page:
|
||||||
self._num_pages = 0
|
self._num_pages = 0
|
||||||
|
@ -77,9 +99,12 @@ class Paginator(object):
|
||||||
return range(1, self.num_pages + 1)
|
return range(1, self.num_pages + 1)
|
||||||
page_range = property(_get_page_range)
|
page_range = property(_get_page_range)
|
||||||
|
|
||||||
QuerySetPaginator = Paginator # For backwards-compatibility.
|
|
||||||
|
QuerySetPaginator = Paginator # For backwards-compatibility.
|
||||||
|
|
||||||
|
|
||||||
class Page(collections.Sequence):
|
class Page(collections.Sequence):
|
||||||
|
|
||||||
def __init__(self, object_list, number, paginator):
|
def __init__(self, object_list, number, paginator):
|
||||||
self.object_list = object_list
|
self.object_list = object_list
|
||||||
self.number = number
|
self.number = number
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
from django.core.paginator import Paginator, Page
|
||||||
|
|
||||||
|
|
||||||
|
class ValidAdjacentNumsPage(Page):
|
||||||
|
|
||||||
|
def next_page_number(self):
|
||||||
|
if not self.has_next():
|
||||||
|
return None
|
||||||
|
return super(ValidAdjacentNumsPage, self).next_page_number()
|
||||||
|
|
||||||
|
def previous_page_number(self):
|
||||||
|
if not self.has_previous():
|
||||||
|
return None
|
||||||
|
return super(ValidAdjacentNumsPage, self).previous_page_number()
|
||||||
|
|
||||||
|
|
||||||
|
class ValidAdjacentNumsPaginator(Paginator):
|
||||||
|
|
||||||
|
def _get_page(self, *args, **kwargs):
|
||||||
|
return ValidAdjacentNumsPage(*args, **kwargs)
|
|
@ -9,6 +9,7 @@ from django.utils import six
|
||||||
from django.utils import unittest
|
from django.utils import unittest
|
||||||
|
|
||||||
from .models import Article
|
from .models import Article
|
||||||
|
from .custom import ValidAdjacentNumsPaginator
|
||||||
|
|
||||||
|
|
||||||
class PaginationTests(unittest.TestCase):
|
class PaginationTests(unittest.TestCase):
|
||||||
|
@ -217,6 +218,20 @@ class PaginationTests(unittest.TestCase):
|
||||||
self.assertEqual(''.join(page2), 'fghijk')
|
self.assertEqual(''.join(page2), 'fghijk')
|
||||||
self.assertEqual(''.join(reversed(page2)), 'kjihgf')
|
self.assertEqual(''.join(reversed(page2)), 'kjihgf')
|
||||||
|
|
||||||
|
def test_get_page_hook(self):
|
||||||
|
"""
|
||||||
|
Tests that a Paginator subclass can use the ``_get_page`` hook to
|
||||||
|
return an alternative to the standard Page class.
|
||||||
|
"""
|
||||||
|
eleven = 'abcdefghijk'
|
||||||
|
paginator = ValidAdjacentNumsPaginator(eleven, per_page=6)
|
||||||
|
page1 = paginator.page(1)
|
||||||
|
page2 = paginator.page(2)
|
||||||
|
self.assertEquals(page1.previous_page_number(), None)
|
||||||
|
self.assertEquals(page1.next_page_number(), 2)
|
||||||
|
self.assertEquals(page2.previous_page_number(), 1)
|
||||||
|
self.assertEquals(page2.next_page_number(), None)
|
||||||
|
|
||||||
|
|
||||||
class ModelPaginationTests(TestCase):
|
class ModelPaginationTests(TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue