Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/flask_sqlalchemy/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ def paginate(
*,
page: int | None = None,
per_page: int | None = None,
default_per_page: int | None = None,
max_per_page: int | None = None,
error_out: bool = True,
count: bool = True,
Expand Down Expand Up @@ -843,6 +844,7 @@ def paginate(
session=self.session(),
page=page,
per_page=per_page,
default_per_page=default_per_page,
max_per_page=max_per_page,
error_out=error_out,
count=count,
Expand Down
22 changes: 19 additions & 3 deletions src/flask_sqlalchemy/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(
self,
page: int | None = None,
per_page: int | None = None,
default_per_page: int | None = None,
max_per_page: int | None = 100,
error_out: bool = True,
count: bool = True,
Expand All @@ -56,6 +57,7 @@ def __init__(
page, per_page = self._prepare_page_args(
page=page,
per_page=per_page,
default_per_page=default_per_page,
max_per_page=max_per_page,
error_out=error_out,
)
Expand All @@ -66,6 +68,9 @@ def __init__(
self.per_page: int = per_page
"""The maximum number of items on a page."""

self.default_per_page: int | None = default_per_page
"""The default number of items on a page."""

self.max_per_page: int | None = max_per_page
"""The maximum allowed value for ``per_page``."""

Expand All @@ -92,6 +97,7 @@ def _prepare_page_args(
*,
page: int | None = None,
per_page: int | None = None,
default_per_page: int | None = None,
max_per_page: int | None = None,
error_out: bool = True,
) -> tuple[int, int]:
Expand All @@ -112,13 +118,19 @@ def _prepare_page_args(
if error_out:
abort(404)

per_page = 20
if default_per_page is None:
per_page = 20
else:
per_page = default_per_page
else:
if page is None:
page = 1

if per_page is None:
per_page = 20
if default_per_page is None:
per_page = 20
else:
per_page = default_per_page

if max_per_page is not None:
per_page = min(per_page, max_per_page)
Expand All @@ -133,7 +145,11 @@ def _prepare_page_args(
if error_out:
abort(404)
else:
per_page = 20
per_page = default_per_page
if default_per_page is None:
per_page = 20
else:
per_page = default_per_page

return page, per_page

Expand Down
31 changes: 29 additions & 2 deletions tests/test_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,25 @@

class RangePagination(Pagination):
def __init__(
self, total: int | None = 150, page: int = 1, per_page: int = 10
self,
total: int | None = 150,
page: int = 1,
per_page: int | None = 10,
default_per_page: int | None = None,
error_out: bool = True,
) -> None:
if total is None:
self._data = range(150)
else:
self._data = range(total)

super().__init__(total=total, page=page, per_page=per_page)
super().__init__(
total=total,
page=page,
per_page=per_page,
default_per_page=default_per_page,
error_out=error_out,
)

if total is None:
self.total = None
Expand All @@ -37,6 +48,7 @@ def test_first_page() -> None:
p = RangePagination()
assert p.page == 1
assert p.per_page == 10
assert p.default_per_page is None
assert p.total == 150
assert p.pages == 15
assert not p.has_prev
Expand Down Expand Up @@ -74,6 +86,21 @@ def test_item_numbers_0() -> None:
assert p.last == 0


def test_default_per_page_invalid_per_page() -> None:
p = RangePagination(per_page=0, default_per_page=10, error_out=False)
assert p.per_page == 10


def test_default_per_page() -> None:
p = RangePagination(per_page=None, default_per_page=None, error_out=False)
assert p.per_page == 20


def test_default_per_page_none() -> None:
p = RangePagination(per_page=None)
assert p.per_page == 20


@pytest.mark.parametrize("total", [0, None])
def test_0_pages(total: int | None) -> None:
p = RangePagination(total=total)
Expand Down
Loading