Login

Page numbers with ... like in Digg

Author:
Ciantic
Posted:
April 15, 2009
Language:
Python
Version:
1.0
Score:
1 (after 1 ratings)

Digg-like page numbering using inclusion tag.

Usage in template:

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

Inclusion template pagination.html:

{% load i18n %}
<div class="pagination">
    <span class="step-links">
    {% if page.has_previous %}
        <a href="?page={{ page.previous_page_number }}" class="previous">{% trans "previous" %}</a>
    {% endif %}

        {% for pnum in begin %}
            {% ifequal page.number pnum %}
                <span class="current">{{ pnum }}</span>
            {% else %}
                <a href="?page={{ pnum }}">{{ pnum }}</a>
            {% endifequal %}
        {% endfor %}

        {% if middle %}
            <span class="continue">...</span>
            {% for pnum in middle %}
                {% ifequal page.number pnum %}
                    <span class="current">{{ pnum }}</span>
                {% else %}
                    <a href="?page={{ pnum }}">{{ pnum }}</a>
                {% endifequal %}
            {% endfor %}
        {% endif %}

        {% if end %}
            <span class="continue">...</span>
            {% for pnum in end %}
                {% ifequal page.number pnum %}
                    <span class="current">{{ pnum }}</span>
                {% else %}
                    <a href="?page={{ pnum }}">{{ pnum }}</a>
                {% endifequal %}
            {% endfor %}
        {% endif %}

    {% if page.has_next %}
        <a href="?page={{ page.next_page_number }}" class="next">{% trans "next" %}</a>
    {% endif %}
    </span>
</div>

Produces:

previous 1 2 ... 4 5 6 7 8 9 10 11 12 ... 17 18 next

Or:

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

Or:

previous 1 2 ... 10 11 12 13 14 15 16 17 18 next

 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
from django import template

register = template.Library()

@register.inclusion_tag('pagination.html')
def pagination(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(last_page_number - before_current_pages - after_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(before_current_pages + 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 = []
    
    return {'page' : page,
            'begin' : begin,
            'middle' : middle,
            'end' : end}
    

More like this

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

Comments

stalker (on December 20, 2009):

IMHO, this code have some bad logic, I replaced line 28 with:

end = range(max(page.number-before_current_pages, 1), last_page_number+1)

and line 33 with:

begin = range(1, min(page.number + after_current_pages, last_page_number)+1)

Without those two changes, one can't access (in some cases) all pages with using only generated links

#

Ciantic (on January 20, 2010):

This is very much in use, and I would like to know when it fails if it fails...

But note that it is intended to drop entries if there are too many. When user selects entry from closer it will show the next entries, so they are not really gone.

#

Please login first before commenting.