- Author:
- SmileyChris
- Posted:
- May 25, 2009
- Language:
- Python
- Version:
- 1.0
- Score:
- 2 (after 2 ratings)
My take on digg-like pagination.
Save the code as 'templatetags/pagination_nav.py' in one of your apps.
It relies on a 'pagination_nav.html' template. Here is a base template:
{% if pages %}
<div class="bottom-pagination-nav">
{% if previous_url %}<a href="{{ previous_url }}">{% else %}<span>{% endif %}« Previous{% if previous_url %}</a>{% else %}</span>{% endif %}
{% for group in pages %}
{% for page in group %}
{% if page.current %}<span>{{ page.number }}</span>{% else %}<a href="{{ page.url }}">{{ page.number }}</a>{% endif %}
{% endfor %}
{% if not forloop.last %}<span>...</span>{% endif %}
{% endfor %}
{% if next_url %}<a href="{{ next_url }}">{% else %}<span>{% endif %}Next »{% if next_url %}</a>{% else %}</span>{% endif %}
</div>
{% endif %}
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | import re
from django import template
from django.http import QueryDict
ADJACENT = 3
CAPS = 1
RE_URL = re.compile('(.*)1(.*)')
register = template.Library()
def page_separator(current, count, adjacent=ADJACENT, caps=CAPS):
if current < adjacent + 1:
adjacent += adjacent - current + 1
elif count - current < adjacent:
adjacent += adjacent - (count - current)
bits = []
if current > (1 + adjacent + caps):
if caps:
bits.append(range(1, caps+1))
start = current - adjacent
else:
start = 1
if current + adjacent < count - caps:
end = current + adjacent
else:
end = count
bits.append(range(start, end+1))
if end != count:
if caps:
bits.append(range(count-caps+1, count+1))
return bits
def get_page_context(page, url_func, adjacent, caps):
if not page:
return {}
current = page.number
count = page.paginator.num_pages
if count < 2:
return {}
pages = []
for page_group in page_separator(current, count, adjacent, caps):
group = []
for number in page_group:
url = url_func(number)
if not url:
return {}
group.append({'url': url, 'number': number,
'current': page.number==number})
pages.append(group)
c = {'pages': pages}
if current > 1:
c['previous_url'] = url_func(current-1)
if current < count:
c['next_url'] = url_func(current+1)
return c
@register.inclusion_tag('pagination-nav.html')
def pagination_nav(page, url, first_page_url=None, adjacent=ADJACENT, caps=CAPS):
"""
Generate Digg-like pagination navigation for URLs like "/entries/page/5/".
Required arguments:
page
A ``django.core.paginator`` ``Page`` object
url
An example URL to navigate to page 1 (the last character ``"1"`` in the
URL gets replaced with the actual page number)
Optional arguments:
first_page_url
An alternate first page exact URL
adjacent
The minimum number of pages to show either side of the current page
(defaults to ``3``)
caps
The number of pages to show at either end (defaults to ``1``)
"""
def make_url(number):
if number == 1 and first_page_url:
return first_page_url
match = RE_URL.match(url)
if not match:
raise template.TemplateSyntaxError(
'URL did not contain the character "1" (which gets replaced with '
'the actual page number).'
)
start, end = match.groups()
return '%s%s%s' % (start, number, end)
return get_page_context(page, make_url, adjacent, caps)
@register.inclusion_tag('pagination-nav.html')
def pagination_nav_qs(page, url='', querydict=None, url_attr='page',
adjacent=ADJACENT, caps=CAPS):
"""
Generate Digg-like pagination navigation for URLs like "/entries/?page=5".
Required arguments:
page
A django.core.paginator Page object
Optional arguments:
url
The base url (defaults to a blank string)
querydict
Usually ``request.GET`` (defaults to an empty ``QueryDict``)
url_attr
The querystring attribute to change (defaults to ``'page'``)
adjacent
The minimum number of pages to show either side of the current page
(defaults to ``3``)
caps
The number of pages to show at either end (defaults to ``1``)
"""
querydict = querydict or QueryDict('')
def make_url(number):
qs = querydict.copy()
if number == 1:
qs.pop(url_attr, None)
else:
qs[url_attr] = number
qs = qs.urlencode()
if qs:
qs = '?%s' % qs
if not url and not qs:
return '.'
return '%s%s' % (url or '', qs)
return get_page_context(page, make_url, adjacent, caps)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 9 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
- Help text hyperlinks by sa2812 1 year, 5 months ago
Comments
Please login first before commenting.