diff --git a/CHANGES b/CHANGES index 4b814a87..822d5ba2 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,10 @@ In development by models. (`#551`_) - Raise the correct error when a model has a table name but no primary key. (`#556`_) +- Allow specifying a ``max_per_page`` limit for pagination, to avoid users + specifying high values in the request args. (`#542`_) +.. _#542: https://github.com/mitsuhiko/flask-sqlalchemy/pull/542 .. _#551: https://github.com/mitsuhiko/flask-sqlalchemy/pull/551 .. _#556: https://github.com/mitsuhiko/flask-sqlalchemy/pull/556 diff --git a/flask_sqlalchemy/__init__.py b/flask_sqlalchemy/__init__.py index d02220b5..b18c1b1f 100644 --- a/flask_sqlalchemy/__init__.py +++ b/flask_sqlalchemy/__init__.py @@ -427,7 +427,7 @@ def first_or_404(self): abort(404) return rv - def paginate(self, page=None, per_page=None, error_out=True): + def paginate(self, page=None, per_page=None, error_out=True, max_per_page=None): """Returns ``per_page`` items from page ``page``. If no items are found and ``page`` is greater than 1, or if page is @@ -469,6 +469,9 @@ def paginate(self, page=None, per_page=None, error_out=True): if per_page is None: per_page = 20 + if max_per_page is not None: + per_page = min(per_page, max_per_page) + if error_out and page < 1: abort(404) diff --git a/tests/test_pagination.py b/tests/test_pagination.py index e80fb3e9..20d8ad1e 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -41,3 +41,11 @@ def index(): # query default p = Todo.query.paginate() assert p.total == 100 + + +def test_query_paginate_more_than_20(app, db, Todo): + with app.app_context(): + db.session.add_all(Todo('', '') for _ in range(20)) + db.session.commit() + + assert len(Todo.query.paginate(max_per_page=10).items) == 10