From ee57bbe42dec51fa38bf8321fdfc91c9f89291d4 Mon Sep 17 00:00:00 2001 From: kalombo Date: Thu, 21 Sep 2017 13:37:51 +0500 Subject: [PATCH 1/2] added max_per_page param to pagination --- flask_sqlalchemy/__init__.py | 5 ++++- tests/test_pagination.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/flask_sqlalchemy/__init__.py b/flask_sqlalchemy/__init__.py index d02220b5..9f7e2b79 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 @@ -462,6 +462,9 @@ def paginate(self, page=None, per_page=None, error_out=True): abort(404) per_page = 20 + else: + if max_per_page is not None: + per_page = min(per_page, max_per_page) else: if page is None: page = 1 diff --git a/tests/test_pagination.py b/tests/test_pagination.py index e80fb3e9..5ee5cb76 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -41,3 +41,18 @@ 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(100)]) + db.session.commit() + + @app.route('/') + def index(): + p = Todo.query.paginate(max_per_page=20) + return '{0} items retrieved'.format(len(p.items)) + + c = app.test_client() + r = c.get('/?per_page=500') + assert r.data.decode('utf8') == '20 items retrieved' From 5cd3def275533c281fa6111ccbd71bc1ab900b31 Mon Sep 17 00:00:00 2001 From: David Lord Date: Wed, 4 Oct 2017 12:57:21 -0700 Subject: [PATCH 2/2] always apply max_per_page add changelog simplify test --- CHANGES | 3 +++ flask_sqlalchemy/__init__.py | 6 +++--- tests/test_pagination.py | 11 ++--------- 3 files changed, 8 insertions(+), 12 deletions(-) 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 9f7e2b79..b18c1b1f 100644 --- a/flask_sqlalchemy/__init__.py +++ b/flask_sqlalchemy/__init__.py @@ -462,9 +462,6 @@ def paginate(self, page=None, per_page=None, error_out=True, max_per_page=None): abort(404) per_page = 20 - else: - if max_per_page is not None: - per_page = min(per_page, max_per_page) else: if page is None: page = 1 @@ -472,6 +469,9 @@ def paginate(self, page=None, per_page=None, error_out=True, max_per_page=None): 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 5ee5cb76..20d8ad1e 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -45,14 +45,7 @@ def index(): def test_query_paginate_more_than_20(app, db, Todo): with app.app_context(): - db.session.add_all([Todo('', '') for _ in range(100)]) + db.session.add_all(Todo('', '') for _ in range(20)) db.session.commit() - @app.route('/') - def index(): - p = Todo.query.paginate(max_per_page=20) - return '{0} items retrieved'.format(len(p.items)) - - c = app.test_client() - r = c.get('/?per_page=500') - assert r.data.decode('utf8') == '20 items retrieved' + assert len(Todo.query.paginate(max_per_page=10).items) == 10