Skip to content

Commit

Permalink
table_page_range appends ellipsis for LazyPaginator if not on last pa…
Browse files Browse the repository at this point in the history
…ge (#707)
  • Loading branch information
tuky authored and jieter committed Oct 21, 2019
1 parent 4962816 commit 80fae05
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
6 changes: 6 additions & 0 deletions django_tables2/paginators.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class UserListView(SingleTableView):

def __init__(self, object_list, per_page, look_ahead=None, **kwargs):
self._num_pages = None
self._final_num_pages = None
if look_ahead is not None:
self.look_ahead = look_ahead

Expand Down Expand Up @@ -91,8 +92,13 @@ def page(self, number):
else:
# This is the last page.
self._num_pages = number
# For rendering purposes in `table_page_range`, we have to remember the final count
self._final_num_pages = number
return Page(objects, number, self)

def is_last_page(self, number):
return number == self._final_num_pages

def _get_count(self):
raise NotImplementedError

Expand Down
3 changes: 3 additions & 0 deletions django_tables2/templatetags/django_tables2.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.utils.http import urlencode

import django_tables2 as tables
from django_tables2.paginators import LazyPaginator
from django_tables2.utils import AttributeDict

register = template.Library()
Expand Down Expand Up @@ -267,6 +268,8 @@ def table_page_range(page, paginator):
ret = [1, "..."] + list(ret)[2:]
if num_pages not in ret:
ret = list(ret)[:-2] + ["...", num_pages]
if isinstance(paginator, LazyPaginator) and not paginator.is_last_page(page.number):
ret.append("...")
return ret


Expand Down
7 changes: 4 additions & 3 deletions docs/pages/pagination.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ set `SingleTableView.table_pagination = False`
Lazy pagination
~~~~~~~~~~~~~~~

The default `~django.core.paginators.Paginator` want to count the number of items,
The default `~django.core.paginators.Paginator` wants to count the number of items,
which might be an expensive operation for large QuerySets.
In those cases, you can use `.LazyPaginator`, which does not perform a count,
but also does not know what the total amount of pages will be.
but also does not know what the total amount of pages will be, until you've hit
the last page.

The `.LazyPaginator` does this by fetching `n + 1` records where the number of records
per page is `n`. If it receives `n` or less records, it knows it is on the last page,
preventing rendering of the 'next' button.
preventing rendering of the 'next' button and further "..." ellipsis.
Usage with `SingleTableView`::

class UserListView(SingleTableView):
Expand Down
17 changes: 15 additions & 2 deletions tests/test_templatetags.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,23 @@ def test_table_page_range_num_pages_equals_page_range_plus_one(self):
table_page_range(paginator.page(7), paginator), [1, "...", 4, 5, 6, 7, 8, 9, 10, 11]
)

def test_table_page_range_lazy(self):
def test_table_page_range_lazy_beginning(self):
paginator = LazyPaginator(range(1, 1000), 10)

self.assertEqual(table_page_range(paginator.page(1), paginator), range(1, 3))

def test_table_page_range_lazy_middle(self):
paginator = LazyPaginator(range(1, 1000), 10)

self.assertEqual(
table_page_range(paginator.page(10), paginator), [1, "...", 4, 5, 6, 7, 8, 9, 10, 11]
table_page_range(paginator.page(10), paginator),
[1, "...", 4, 5, 6, 7, 8, 9, 10, 11, "..."],
)

def test_table_page_range_lazy_last_page(self):
paginator = LazyPaginator(range(1, 1000), 10)

self.assertEqual(
table_page_range(paginator.page(100), paginator),
[1, "...", 93, 94, 95, 96, 97, 98, 99, 100],
)

0 comments on commit 80fae05

Please sign in to comment.