Skip to content

Instantly share code, notes, and snippets.

@zhangsen
Created September 21, 2011 08:50
Show Gist options
  • Save zhangsen/1231609 to your computer and use it in GitHub Desktop.
Save zhangsen/1231609 to your computer and use it in GitHub Desktop.
django-simple-pager
#
# This piece of code is in the public domain.
# <[email protected]>
#
#### the filter ####
def insert_ellipse(lst, ellipse=0):
'''Insert ellipse where it's not sequential
An ellipse is represented by @ellipse.
E.g.:
[1, 2, 5] -> [1, 2, 0, 5]
[1, 2, 4] -> [1, 2, 3, 4]
The last example is that if only one step is missing, just add it instead
of an ellipse.
'''
if len(lst) <= 1:
return list(lst[:])
gap = lst[1] - lst[0]
if gap <= 1:
return [lst[0]] + insert_ellipse(lst[1:], ellipse)
elif gap == 2:
return [lst[0], lst[0] + 1] + insert_ellipse(lst[1:], ellipse)
else:
return [lst[0], ellipse] + insert_ellipse(lst[1:], ellipse)
@register.filter
def pick_pages(num_pages, current):
'''pick pages to display in the pager
It's like: 1 ... (x-2) (x-1) (x) (x+1) (x+2) ... N.
'''
ret = []
for p in range(current - 2, current):
if p >= 1:
ret.append(p)
ret.append(current)
for p in range(current + 1, current + 3):
if p <= num_pages:
ret.append(p)
if ret[0] != 1:
ret.insert(0, 1)
if ret[-1] != num_pages:
ret.append(num_pages)
ret = insert_ellipse(ret)
return ret
#### template ####
{% if page.paginator.num_pages > 1 %}
<div class="pager">
{% if page.number > 1 %}
<a href="{% add_get_param request 'page' page.previous_page_number %}">
<span class="page-number prev">←prev</span>
</a>
{% endif %}
{% for p in page.paginator.num_pages|pick_pages:page.number %}
{% if p == page.number %}
<span class="page-number current">{{p}}</span>
{% else %}{% if p == 0 %}
<span class="page-number ellipse">&hellip;</span>
{% else %}
<a href="{% add_get_param request 'page' p %}">
<span class="page-number">{{p}}</span>
</a>
{% endif %}
{% endif %}
{% endfor %}
{% if page.number < page.paginator.num_pages %}
<a href="{% add_get_param request 'page' page.next_page_number %}">
<span class="page-number next">next→</span>
</a>
{% endif %}
</div>
{% endif %}
#### unittest / examples ####
def test_insert_ellipse(self):
for lst, result in (
((0, 1, 3), [0, 1, 2, 3]),
((0, 1, 4), [0, 1, None, 4]),
):
self.assertEqual(insert_ellipse(lst, ellipse=None), result)
for lst, result in (
((1,), [1]),
((1, 3, 5), [1, 2, 3, 4, 5]),
((3, 7), [3, 0, 7]),
):
self.assertEqual(points_utils.insert_ellipse(lst), result)
def test_filter_pick_pages(self):
for num_pages, current, output in (
(3, 1, [1, 2, 3]),
(5, 1, [1, 2, 3, 4, 5]),
(5, 3, [1, 2, 3, 4, 5]),
(6, 1, [1, 2, 3, 0, 6]),
(6, 5, [1, 2, 3, 4, 5, 6]),
(6, 6, [1, 0, 4, 5, 6]),
(1, 1, [1]),
):
self.assertEqual(pick_pages(num_pages, current), output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment