Django Pagination Template Tag that allows unlimited customization to the current Django Pagination.
Automatically creates template variables that can be used to display the pagination in any format that you can desire such as
Previous 1 2 3 [ 4 ] 5 6 7 Next
First Previous 12 14 15 16 17 [ 18 ] 19 20 22 25 Next Last
Showing 25 of 80 Results
First Page 23 27 30 33 [ 36 ] 38 41 44 50 Next Last
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | """ XPaginate FILE """
from math import *
from django import template
from django.template import Library, Node
register = template.Library()
"""
Django Pagination Template Tag
Allows for complete customization on pagination display
Renders pages a template context with the following vars avaliable
total_items: List of total pagination items
current: Current Page pagination is on
per_page: How many items per page
has_previous: Has links to display that go to previous pages
has_next: Has links to display that go fowards pages
foward_pages: Dictionary contaning forward page numbers
previous_links: Dictionary containing previous page numbers
has_jump_previous: Has links that "jump" backwords through previous page numbers
has_jump_foward: Has page numbers that "jump" through foward page numbers
foward_page_jump: Dictionary containg list of forward jumping page numbers
foward_page_jump: Dictionary containg list of previous jumping page numbers
show_last: Boolean that smartly determains the current page location to display a link to the last page
show_last: Boolean that smartly determains the current page location to display a link to the first page
"""
class XPaginate:
def __init__(self, uri, total_items, current, per_page, show, jump, range):
self.total_items = int(total_items)
self.current = int(current)
self.per_page = int(per_page)
self.show = int(show)
self.jump = jump
self.range = int(range)
self.jump_calc = 2
self.uri = uri
if self.current is 0:
self.current = 1
# Total number of pages
self.total_pages = int(ceil(float(total_items) / float(per_page)))
if self.current is not 1:
self.has_previous = True
else:
self.has_previous = False
if self.current < self.total_pages:
self.has_next = True
else:
self.has_next = False
# Get the first foward set of page links if avaliable
self.foward_pages = []
if self.has_next:
a = self.current
self.foward = int(self.current + 1)
total = 0
while total is not self.show:
a = a + 1
total = total + 1
if a <= self.total_pages:
if total is self.show:
last_foward = a
self.foward_pages.append(a)
if last_foward is self.total_pages or (last_foward + self.show) > self.total_pages:
self.show_last = False
else:
self.show_last = True
#print self.foward_pages, '\n'
# GET the set of previous pages
self.previous_pages = []
if self.has_previous:
self.previous = int(self.current - 1)
a = int((self.current - 1) - self.show)
total = 0
while total is not self.show:
a = a + 1
total = total + 1
if a <= self.total_pages and a is not 0:
if total is self.show:
last_previous = int(a)
self.previous_pages.append(a)
#print self.previous_pages, '\n'
# Calculate if we have the ability to jump foward pages
if self.jump and (self.current - ceil(self.range * self.jump_calc)) >= 2:
self.has_jump_previous = True
else:
self.has_jump_previous = False
if self.jump and (self.current + ceil(self.range * self.jump_calc)) < self.total_pages:
self.has_jump_foward = True
else:
self.has_jump_foward = False
## Calc Jump pages foward
if self.has_jump_foward:
a = last_foward
total = 0
self.foward_page_jump = []
while total is not self.range:
total = total + 1
a = int(float(ceil(a * self.jump_calc)))
if a <= self.total_pages:
self.foward_page_jump.append(a)
if self.has_jump_previous:
a = int(last_previous)
total = 0
self.previous_page_jump = []
while total is not self.range:
total = total + 1
a = int(ceil(a / float(self.jump_calc)))
if a <= self.total_pages and a >= 2:
self.previous_page_jump.insert(0, a)
class RenderXPage(Node):
def __init__(self, uri, total_items, current, per_page, show, jump, range):
self.total_items = template.Variable(total_items)
self.current = template.Variable(current)
self.uri = template.Variable(uri)
if not per_page:
self.per_page = 10
else:
self.per_page = per_page
if not show:
self.show = 3
else:
self.show = show
if not jump:
self.jump = True
else:
self.jump = jump
if not range:
self.range = 3
else:
self.range = range
def render(self, context):
try:
context['xpaginate'] = XPaginate(self.uri.resolve(context), self.total_items.resolve(context), self.current.resolve(context), self.per_page, self.show, self.jump, self.range)
except:
pass
return ''
def xpaginator(parser, token):
tokens = token.split_contents()
return RenderXPage(tokens[1], tokens[2], tokens[3], tokens[4], tokens[5], tokens[6], tokens[7])
register.tag('xpaginator', xpaginator)
""" XPaginate Tempalte File """
<div class="pagination">
{% if xpaginate.has_previous %}
<a href="{{ xpaginate.uri }}{{ xpaginate.previous }}"><< Previous</a>
{% if xpaginate.has_jump_previous %}
{% for a in xpaginate.previous_page_jump %}
<a href="{{ xpaginate.uri }}{{ a }}">{{ a }}</a> ...
{% endfor %}
{% endif %}
{% for a in xpaginate.previous_pages %}
<a href="{{ xpaginate.uri }}{{ a }}">{{ a }}</a>
{% endfor %}
{% endif %}
<span class="current">[ {{ xpaginate.current }} ]</span>
{% if xpaginate.has_next %}
{% for a in xpaginate.foward_pages %}
<a href="{{ xpaginate.uri }}{{ a }}">{{ a }}</a>
{% endfor %}
{% if xpaginate.show_last %}
... <a href="{{ xpaginate.uri }}{{ xpaginate.total_pages }}">{{ xpaginate.total_pages }}</a>
{% endif %}
<a href="{{ xpaginate.uri }}{{ xpaginate.foward }}">Next >></a>
{% endif %}
</div>
""" DIRECTORY STRUCTURE """
|-- xpaginate
|-- templatetags
|-- xpaginate.py
|-- path/to/view/templates
|-- xpaginate.html
""" USAGE EXAMPLE """
NOTE:
You must add **xpaginate** to you INSTALLED_APPS list
[ view.py ]
from urlgen.urlgen import urlGen
cards = Card.objects.all().order_by('name')
items = cards.count()
paginator = Paginator(cards, 16) # Show 25 contacts per page
# Make sure page request is an int. If not, deliver first page.
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
# If page request (9999) is out of range, deliver last page of results.
try:
cards = paginator.page(page)
except (EmptyPage, InvalidPage):
cards = paginator.page(paginator.num_pages)
"""
USES URI Generator Snippet
http://www.djangosnippets.org/snippets/1734/
"""
url = urlGen()
pageURI = url.generate('page', request.GET)
cards = cards.object_list
return render_to_response('template.html', {'cards': cards,
'total_item': items,
'pageURI': pageURI,
'current': page
}, context_instance=RequestContext(request))
[ template.html ]
{% for card in cards %}
<li>
<span>{{ card.name }}</span>
</li>
{% endfor %}
{% load xpaginator %}
{% xpaginator pageURI total_item current 16 1 True 1 %}
{% include "xpaginate.html" %}
Template Tag accepts the following parameters
uri: URI to use for link, EX ?page=
total_items: total number of items
current: current page that user is on
per_page: items displayed per page
show: OPTIONAL: how many links to display on left and right of current page
jump: OPTIONAL: create a list of links that jump through pages increasing by 1.2* the current
range: Number of jumped links to calculate and display on for forward and reverse
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Hi, first of all thanks for the snippet. I found a bug depending on the value assumed by "self.current" variable. If self.current is greater than 256, the test "self.current is not self.total_pages" (at line 57) became true...why not use the '!=' operator?
#
Thanks for the find, snippet updated to accommodate.
#
Isn't this some error?
Two variables with the same name and different descriptions? And what about showing the link to the first page?
Besides that you don't write "determains" but "determines".
#
Please login first before commenting.