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
|
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".
#