Last active
April 29, 2020 14:43
-
-
Save sartim/267f825cb48aca86a8c33780c9801f60 to your computer and use it in GitHub Desktop.
SQLAlchemy Pagination In Flask
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from math import ceil | |
from flask import abort, request | |
class Pagination: | |
def __init__(self, query=None, page=None, per_page=None, total=None, items=None): | |
self.query = query | |
self.page = page | |
self.per_page = per_page | |
self.total = total | |
self.items = items | |
@property | |
def pages(self): | |
if self.per_page == 0 or self.total is None: | |
pages = 0 | |
else: | |
pages = int(ceil(self.total / float(self.per_page))) | |
return pages | |
def prev(self, error_out=False): | |
assert self.query is not None, 'a query object is required ' \ | |
'for this method to work' | |
return self.query.paginate(self.page - 1, self.per_page, error_out) | |
@property | |
def prev_num(self): | |
if not self.has_prev: | |
return None | |
return self.page - 1 | |
@property | |
def has_prev(self): | |
return self.page > 1 | |
def next(self, error_out=False): | |
assert self.query is not None, 'a query object is required ' \ | |
'for this method to work' | |
return self.query.paginate(self.page + 1, self.per_page, error_out) | |
@property | |
def has_next(self): | |
return self.page < self.pages | |
@property | |
def next_num(self): | |
if not self.has_next: | |
return None | |
return self.page + 1 | |
def iter_pages(self, left_edge=2, left_current=2, | |
right_current=5, right_edge=2): | |
last = 0 | |
for num in range(1, self.pages + 1): | |
if num <= left_edge or \ | |
(self.page - left_current - 1 < num < self.page + right_current) or \ | |
num > self.pages - right_edge: | |
if last + 1 != num: | |
yield None | |
yield num | |
last = num | |
@classmethod | |
def paginate(cls, obj=None, page=None, per_page=None, error_out=True, max_per_page=None, count=True): | |
""":param obj: Query Object E.g User.query""" | |
if obj: | |
if request: | |
if page is None: | |
try: | |
page = int(request.args.get('page', 1)) | |
except (TypeError, ValueError): | |
if error_out: | |
abort(404) | |
page = 1 | |
if per_page is None: | |
try: | |
per_page = int(request.args.get('per_page', 20)) | |
except (TypeError, ValueError): | |
if error_out: | |
os.abort(404) | |
per_page = 20 | |
else: | |
if page is None: | |
page = 1 | |
if per_page is None: | |
per_page = 20 | |
if max_per_page is not None: | |
per_page = min(per_page, max_per_page) | |
if page < 1: | |
if error_out: | |
abort(404) | |
else: | |
page = 1 | |
if per_page < 0: | |
if error_out: | |
abort(404) | |
else: | |
per_page = 20 | |
items = obj.limit(per_page).offset((page - 1) * per_page).all() | |
if not items and page != 1 and error_out: | |
abort(404) | |
if not count: | |
total = None | |
elif page == 1 and len(items) < per_page: | |
total = len(items) | |
else: | |
total = obj.order_by(None).count() | |
return Pagination(obj, page, per_page, total, items) | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment