-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from Overseas-Student-Living/query-pagination
Add apply_pagination function to allow query pagination
- Loading branch information
Showing
6 changed files
with
536 additions
and
13 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,7 @@ class BadFilterFormat(Exception): | |
|
||
class BadQuery(Exception): | ||
pass | ||
|
||
|
||
class InvalidPage(Exception): | ||
pass |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,92 @@ | ||
# -*- coding: utf-8 -*- | ||
import math | ||
from collections import namedtuple | ||
|
||
from sqlalchemy_filters.exceptions import InvalidPage | ||
|
||
def apply_pagination(query, offset, limit): | ||
# TODO | ||
raise NotImplemented() | ||
|
||
def apply_pagination(query, page_number=None, page_size=None): | ||
"""Apply pagination to a SQLAlchemy query object. | ||
:param page_number: | ||
Page to be returned (starts and defaults to 1). | ||
:param page_size: | ||
Maximum number of results to be returned in the page (defaults | ||
to the total results). | ||
:returns: | ||
A 2-tuple with the paginated SQLAlchemy query object and | ||
a pagination namedtuple. | ||
The pagination object contains information about the results | ||
and pages: ``page_size`` (defaults to ``total_results``), | ||
``page_number`` (defaults to 1), ``num_pages`` and | ||
``total_results``. | ||
Basic usage:: | ||
query, pagination = apply_pagination(query, 1, 10) | ||
>>> len(query) | ||
10 | ||
>>> pagination.page_size | ||
10 | ||
>>> pagination.page_number | ||
1 | ||
>>> pagination.num_pages | ||
3 | ||
>>> pagination.total_results | ||
22 | ||
>>> page_size, page_number, num_pages, total_results = pagination | ||
""" | ||
total_results = query.count() | ||
query = _limit(query, page_size) | ||
|
||
# Page size defaults to total results | ||
if page_size is None or (page_size > total_results and total_results > 0): | ||
page_size = total_results | ||
|
||
query = _offset(query, page_number, page_size) | ||
|
||
# Page number defaults to 1 | ||
if page_number is None: | ||
page_number = 1 | ||
|
||
num_pages = _calculate_num_pages(page_number, page_size, total_results) | ||
|
||
Pagination = namedtuple( | ||
'Pagination', | ||
['page_number', 'page_size', 'num_pages', 'total_results'] | ||
) | ||
return query, Pagination(page_number, page_size, num_pages, total_results) | ||
|
||
|
||
def _limit(query, page_size): | ||
if page_size is not None: | ||
if page_size < 0: | ||
raise InvalidPage( | ||
'Page size should not be negative: {}'.format(page_size) | ||
) | ||
|
||
query = query.limit(page_size) | ||
|
||
return query | ||
|
||
|
||
def _offset(query, page_number, page_size): | ||
if page_number is not None: | ||
if page_number < 1: | ||
raise InvalidPage( | ||
'Page number should be positive: {}'.format(page_number) | ||
) | ||
|
||
query = query.offset((page_number - 1) * page_size) | ||
|
||
return query | ||
|
||
|
||
def _calculate_num_pages(page_number, page_size, total_results): | ||
if page_size == 0: | ||
return 0 | ||
|
||
return math.ceil(total_results / page_size) |
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
Oops, something went wrong.