Login

Improved many-page pagination

Author:
dokterbob
Posted:
September 16, 2010
Language:
Python
Version:
1.2
Score:
1 (after 1 ratings)

This one was adapted from Page numbers with ... like in Digg. See that one for more reference.

Digg-like page numbering using inclusion tag.

Usage in template:

{% load pagination %} {% pagination yourpage %}

Inclusion template pagination.html:

{% if page.has_previous %}
    <a href="?page={{ page.previous_page_number }}"><img src="{{ MEDIA_URL }}images/page/cyclenav_l.png" alt="Previous page" /></a> 
{% endif %}

{% for pnum in begin %}
    <a href="?page={{ pnum }}"{% if page.number == pnum %} class="active"{% endif %}>{{ pnum }}</a> 
{% endfor %}

{% if middle %}
    <strong>...</strong>

    {% for pnum in middle %}
        <a href="?page={{ pnum }}"{% if page.number == pnum %} class="active"{% endif %}>{{ pnum }}</a> 
    {% endfor %}
{% endif %}

{% if end %}
    <strong>...</strong>

    {% for pnum in end %}
        <a href="?page={{ pnum }}"{% if page.number == pnum %} class="active"{% endif %}>{{ pnum }}</a> 
    {% endfor %}
{% endif %}

{% if page.has_next %}
    <a href="?page={{ page.next_page_number }}"><img src="{{ MEDIA_URL }}images/page/cyclenav_l.png" alt="Previous page" /></a> 
{% endif %}`

Produces:

previous_img 1 2 ... 4 5 6 7 8 9 10 11 12 ... 17 18 next_img

Or:

1 2 3 4 5 6 7 8 ... 17 18 next_img

Or:

previous_img 1 2 ... 10 11 12 13 14 15 16 17 18 next_img

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from django import template

register = template.Library()

@register.inclusion_tag('pagination.html', takes_context=True)
def pagination(context, page, begin_pages=2, end_pages=2, before_current_pages=4, after_current_pages=4):
    # Digg-like pages
    before = max(page.number - before_current_pages - 1, 0)
    after = page.number + after_current_pages
    
    begin = page.paginator.page_range[:begin_pages]
    middle = page.paginator.page_range[before:after]
    end = page.paginator.page_range[-end_pages:]
    last_page_number = end[-1]
    
    def collides(firstlist, secondlist):
        """ Returns true if lists collides (have same entries)
        
        >>> collides([1,2,3,4],[3,4,5,6,7])
        True
        >>> collides([1,2,3,4],[5,6,7])
        False
        """
        return any(item in secondlist for item in firstlist)
    
    # If middle and end has same entries, then end is what we want
    if collides(middle, end):
        end = range(max(page.number-before_current_pages, 1), last_page_number+1)

        middle = []
        
    # If begin and middle ranges has same entries, then begin is what we want
    if collides(begin, middle):
        begin = range(1, min(page.number + after_current_pages, last_page_number)+1)

        middle = []
        
    # If begin and end has same entries then begin is what we want
    if collides(begin, end):
        begin = range(1, last_page_number+1)
        end = []
    
    context.update({'page' : page,
                    'begin' : begin,
                    'middle' : middle,
                    'end' : end})
    
    return context

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 12 months ago

Comments

Please login first before commenting.