← Back to the web2py-plugin list
Paginator
A standard paginator which can be used with SQLTABLE. The basic design is inspired by this discussion.
Demo
| paginate_info | : | Display: 1 - 25 of 99 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| paginate_selector | : | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| paginator | : | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| table | : |
|
Usage
-
controllers/plugin_paginator.py
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.from plugin_paginator import Paginator, PaginateSelector, PaginateInfo
from plugin_solidtable import SOLIDTABLE
from gluon.contrib.populate import populate
db = DAL('sqlite:memory:')
db.define_table('product', Field('name'))
populate(db.product, 99)
def index():
query = db.product.id > 0
################################ The core ######################################
paginate_selector = PaginateSelector(anchor='main')
paginator = Paginator(paginate=paginate_selector.paginate,
extra_vars={'v':1}, anchor='main',
renderstyle=True)
paginator.records = db(query).count()
paginate_info = PaginateInfo(paginator.page, paginator.paginate, paginator.records)
rows = db(query).select(limitby=paginator.limitby())
################################################################################
table = SOLIDTABLE(rows, renderstyle=True)
return dict(table=table, paginator=paginator,
paginate_selector=paginate_selector, paginate_info=paginate_info)
Source code
-
modules/plugin_paginator.py
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.# original by http://groups.google.com/group/web2py/browse_frm/thread/d1ec3ded48839071#
from gluon import *
from gluon.storage import Messages
# For referencing static and views from other application
import os
APP = os.path.basename(os.path.dirname(os.path.dirname(__file__)))
class Paginator(DIV):
def __init__(self, paginate=10, records=100,
renderstyle=False, page_var='page',
anchor="", extra_vars={}, **attributes):
DIV.__init__(self, **attributes)
self.attributes['_class'] = 'paginator'
self.paginate, self.records, self.page_var, self.anchor, self.extra_vars = (
paginate, records, page_var, anchor, extra_vars
)
self.page = int(current.request.get_vars.get(self.page_var) or 1)
self.messages = Messages(current.T)
self.messages.prev = 'Prev'
self.messages.next = 'Next'
if renderstyle:
_url = URL(APP, 'static', 'plugin_paginator/paginator.css')
if _url not in current.response.files:
current.response.files.append(_url)
def _url(self, page):
vars = current.request.get_vars.copy()
vars[self.page_var] = page
vars.update(self.extra_vars)
return URL(args=current.request.args, vars=vars, anchor=self.anchor)
def limitby(self):
return (self.paginate * (self.page - 1), self.paginate * self.page)
def xml(self):
self.components[:] = []
pages = (self.records - 1) / self.paginate + 1
if (self.records > self.paginate and
pages == 1 and pages * self.paginate != self.records):
pages = 2
elif pages == 0 and self.records != 0:
pages = 1
if pages > 1:
def _get_page_el(page):
if self.page == page:
return EM(page)
else:
return A(page, _title=page,
_href=self._url(page),
_class='w2p_trap')
if self.page != 1:
self.append(
A(self.messages.prev, _href=self._url(self.page - 1),
_title=(self.page - 1), _class='previous_page w2p_trap'))
_pad_prev = 2
_pad_next = 3 if self.page > 3 else 7 - self.page
if self.page - _pad_prev > 1:
self.append(_get_page_el(1))
if self.page - _pad_prev > 2:
self.append(SPAN('... '))
elif self.page - _pad_prev == 1:
self.append(_get_page_el(2))
for page in range(max(self.page - _pad_prev, 1),
min(self.page + _pad_next, pages + 1)):
self.append(_get_page_el(page))
if self.page + _pad_next <= pages:
if self.page + _pad_next <= pages - 2:
self.append(SPAN('... '))
elif self.page + _pad_next == pages - 1:
self.append(_get_page_el(pages - 1))
self.append(_get_page_el(pages))
if pages > self.page:
self.append(
A(self.messages.next, _href=self._url(self.page + 1),
_title=(self.page + 1), _class='next_page w2p_trap'))
return DIV.xml(self)
class PaginateSelector(SPAN):
def __init__(self, paginates=(10, 25, 50, 100),
paginate_var='paginate', page_var='page',
anchor=None, style='text', **attributes):
SPAN.__init__(self, **attributes)
self.attributes['_class'] = 'paginate_selector'
self.paginates, self.paginate_var, self.page_var, self.anchor, self.style = (
paginates, paginate_var, page_var, anchor, style
)
self.paginate = int(current.request.get_vars.get(self.paginate_var, paginates[0]))
self.messages = Messages(current.T)
self.messages.paginate = 'Paginate: '
self.messages.option = ''
def _url(self, paginate):
vars = current.request.get_vars.copy()
vars[self.page_var] = 1
vars[self.paginate_var] = paginate
return URL(args=current.request.args, vars=vars, anchor=self.anchor)
def xml(self):
if self.style == 'text':
def _get_paginate_link(_paginate):
if _paginate == self.paginate:
return str(_paginate)
else:
return A(_paginate, _href=self._url(_paginate), _class='w2p_trap').xml()
inner = XML(self.messages.paginate +
', '.join([_get_paginate_link(_paginate) for _paginate in self.paginates]))
return SPAN(inner, **self.attributes).xml()
elif self.style == 'select':
options = [OPTION(self.messages.option % _paginate if self.messages.option else _paginate,
_value=_paginate) for _paginate in self.paginates]
return SPAN(self.messages.paginate,
SELECT(options, value=self.paginate,
_onchange='location.href="%s".replace("__paginate__", this.value)' % self._url('__paginate__')
), **self.attributes).xml()
else:
raise RuntimeError
class PaginateInfo(SPAN):
def __init__(self, page, paginate, records, **attributes):
SPAN.__init__(self, **attributes)
self.attributes['_class'] = 'paginate_info'
self.page, self.paginate, self.records = (
page, paginate, records
)
self.messages = Messages(current.T)
self.messages.display_without_span = 'Display: <b>%(total)s</b>'
self.messages.display_with_span = 'Display: <b>%(start)s - %(end)s</b> of <b>%(total)s</b>'
def xml(self):
if self.records <= self.paginate:
inner = XML(self.messages.display_without_span %
dict(total=self.records))
else:
inner = XML(self.messages.display_with_span %
dict(start=(self.page - 1) * self.paginate + 1, end=self.page * self.paginate,
total=self.records))
return SPAN(inner, **self.attributes).xml()
