Skip to content

Commit

Permalink
add source files
Browse files Browse the repository at this point in the history
  • Loading branch information
lixxu committed Oct 7, 2012
1 parent 545d757 commit 7e0f593
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 1 deletion.
31 changes: 31 additions & 0 deletions LICENSE
@@ -0,0 +1,31 @@
Copyright (c) 2012 by Lix Xu.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.

* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 changes: 24 additions & 1 deletion README.md
@@ -1,4 +1,27 @@
flask-paginate
==============

Pagination support for flask
Paginate support for flask framework (study from will_paginate).
Use bootstrap for css framework
It requires Python2.6+ as string.format syntax.

If you want to show pagination-info
("Total <b>100</b> posts, displaying <b>20 - 30</b>")
above the pagination links,
please add below lines to your css file

.pagination-page-info {
padding: .6em;
padding-left: 0;
width: 40em;
margin: .5em;
margin-left: 0;
font-size: 12px;
}
.pagination-page-info b {
color: black;
background: #6aa6ed;
padding-left: 2px;
padding: .1em .25em;
font-size: 150%;
}
1 change: 1 addition & 0 deletions flaskext/__init__.py
@@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)
191 changes: 191 additions & 0 deletions flaskext/paginate/__init__.py
@@ -0,0 +1,191 @@
#!/usr/bin/env python
#-*- coding: utf-8 -*-

from __future__ import unicode_literals
from flask import request, url_for, session

first_page = '<li class="disabled"><a href="#">{0}</a></li>'
last_page = '<li class="disabled"><a href="#">{0}</a></li>'
prev_page = '<li><a href="{0}">{1}</a></li>'
next_page = '<li><a href="{0}">{1}</a></li>'
active_page = '<li class="active"><a href="#">{0}</a></li>'
link = '<li><a href="{0}">{1}</a></li>'
gap_marker = '<li class="disabled"><a href="#">...</a></li>'
disabled_page = '<li class="disabled"><a href="#">{0}</a></li>'

prev_label = ' &laquo; '
next_label = ' &raquo; '

display_msg = '''Displaying <b>{start} - {end}</b> records in total
<b>{total}</b>'''

search_msg = '''Found <b>{found}</b> records in total <b>{total}</b>,
displaying <b>{start} - {end}</b>'''


class Pagination(object):
def __init__(self, found=0, **kwargs):
self.found = found
self.page = kwargs.get('page', 1)
self.per_page = kwargs.get('per_page', 10)
self.inner_window = kwargs.get('inner_window', 2)
self.outer_window = kwargs.get('outer_window', 1)
self.prev_label = kwargs.get('prev_label') or prev_label
self.next_label = kwargs.get('next_label') or next_label
self.search = kwargs.get('search', False)
self.total = kwargs.get('total', 0)
self.display_msg = kwargs.get('display_msg') or display_msg
self.search_msg = kwargs.get('search_msg') or search_msg

@property
def total_pages(self):
pages = divmod(self.total, self.per_page)
return pages[0] + 1 if pages[1] else pages[0]

@property
def has_prev(self):
return self.page > 1

@property
def has_next(self):
return self.page < self.total_pages

@property
def endpoint(self):
return request.endpoint

@property
def args(self):
args = request.args.to_dict()
args.pop('page', None)
return args

@property
def prev_page(self):
if self.has_prev:
return prev_page.format(url_for(self.endpoint,
page=self.page - 1,
**self.args
),
self.prev_label
)

return disabled_page.format(self.prev_label)

@property
def next_page(self):
if self.has_next:
return next_page.format(url_for(self.endpoint,
page=self.page + 1,
**self.args
),
self.next_label
)

return disabled_page.format(self.next_label)

@property
def first_page(self):
# current page is first page
if self.has_prev:
return link.format(url_for(self.endpoint, **self.args), 1)

return active_page.format(1)

@property
def last_page(self):
if self.has_next:
return link.format(url_for(self.endpoint,
page=self.total_pages,
**self.args
),
self.total_pages
)

return active_page.format(self.page)

@property
def pages(self):
if self.total_pages < self.inner_window * 2 - 1:
return range(1, self.total_pages + 1)

pages = []
win_from = self.page - self.inner_window
win_to = self.page + self.inner_window
if win_to > self.total_pages:
win_from -= win_to - self.total_pages
win_to = self.total_pages

if win_from < 1:
win_to = win_to + 1 - win_from
win_from = 1
if win_to > self.total_pages:
win_to = self.total_pages

if win_from > self.inner_window:
pages.extend(range(1, self.outer_window + 1 + 1))
pages.append(None)
else:
pages.extend(range(1, win_to + 1))

if win_to < self.total_pages - self.inner_window + 1:
if win_from > self.inner_window:
pages.extend(range(win_from, win_to + 1))

pages.append(None)
pages.extend(range(self.total_pages - 1, self.total_pages + 1))
elif win_from > self.inner_window:
pages.extend(range(win_from, self.total_pages + 1))
else:
pages.extend(range(win_to + 1, self.total_pages + 1))

return pages

def single_page(self, page):
if page == self.page:
return active_page.format(page)

if page == 1:
return self.first_page

if page == self.total_pages:
return self.last_page

return link.format(url_for(self.endpoint, page=page, **self.args),
page
)

@property
def links(self):
if self.total_pages <= 1:
return ''

s = ['<div class="pagination"><ul>']
s.append(self.prev_page)
for page in self.pages:
s.append(self.single_page(page) if page else gap_marker)

s.append(self.next_page)
s.append('</ul></div>')
return ''.join(s)

@property
def info(self):
start = 1 + (self.page - 1) * self.per_page
end = start + self.per_page - 1
if end > self.total:
end = self.total if not self.search else self.found

if start > self.total:
start = self.total if not self.search else self.found

s = ['<div class="pagination-page-info">']
page_msg = self.search_msg if self.search else self.display_msg
s.append(page_msg.format(found=self.found,
total=self.total,
start=start,
end=end,
)
)
s.append('</div>')
return ''.join(s)
35 changes: 35 additions & 0 deletions setup.py
@@ -0,0 +1,35 @@
"""
Flask-paginate
--------------
Simple paginate for Flask (study from will_paginate).
Use bootstrap css framework
"""
from setuptools import setup

setup(
name='Flask-paginate',
version='0.1',
url='https://github.com/lixxu/flask-paginate',
license='BSD',
author='Lix Xu',
author_email='xuzenglin@gmail.com',
description='Simple Paginate support for Flask',
long_description=__doc__,
namespace_packages=['flaskext'],
packages=['flaskext', 'flaskext.paginate'],
zip_safe=False,
platforms='any',
install_requires=[
'Flask',
],
classifiers=[
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries :: Python Modules'
]
)

0 comments on commit 7e0f593

Please sign in to comment.