summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Galigniana <marcelogaligniana@gmail.com>2023-04-09 22:30:40 -0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-04-12 14:02:28 +0200
commitdfc720c521062cdefd64bc48a11838b0fa583439 (patch)
tree8b38ad33d223e8c56f21a609fe504ac06cef5b92
parent041b0a359a0a80e147b47c6ae5f11bca9dd3b28a (diff)
Fixed #27505 -- Allowed customizing Paginator's error messages.
-rw-r--r--django/core/paginator.py25
-rw-r--r--docs/ref/paginator.txt36
-rw-r--r--docs/releases/5.0.txt6
-rw-r--r--tests/pagination/tests.py28
4 files changed, 90 insertions, 5 deletions
diff --git a/django/core/paginator.py b/django/core/paginator.py
index 131ea0f811..7b3189cc8b 100644
--- a/django/core/paginator.py
+++ b/django/core/paginator.py
@@ -28,13 +28,30 @@ class Paginator:
# Translators: String used to replace omitted page numbers in elided page
# range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10].
ELLIPSIS = _("…")
+ default_error_messages = {
+ "invalid_page": _("That page number is not an integer"),
+ "min_page": _("That page number is less than 1"),
+ "no_results": _("That page contains no results"),
+ }
- def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
+ def __init__(
+ self,
+ object_list,
+ per_page,
+ orphans=0,
+ allow_empty_first_page=True,
+ error_messages=None,
+ ):
self.object_list = object_list
self._check_object_list_is_ordered()
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
+ self.error_messages = (
+ self.default_error_messages
+ if error_messages is None
+ else self.default_error_messages | error_messages
+ )
def __iter__(self):
for page_number in self.page_range:
@@ -47,11 +64,11 @@ class Paginator:
raise ValueError
number = int(number)
except (TypeError, ValueError):
- raise PageNotAnInteger(_("That page number is not an integer"))
+ raise PageNotAnInteger(self.error_messages["invalid_page"])
if number < 1:
- raise EmptyPage(_("That page number is less than 1"))
+ raise EmptyPage(self.error_messages["min_page"])
if number > self.num_pages:
- raise EmptyPage(_("That page contains no results"))
+ raise EmptyPage(self.error_messages["no_results"])
return number
def get_page(self, number):
diff --git a/docs/ref/paginator.txt b/docs/ref/paginator.txt
index 670c06e6a8..8afadbe6f8 100644
--- a/docs/ref/paginator.txt
+++ b/docs/ref/paginator.txt
@@ -14,7 +14,7 @@ For examples, see the :doc:`Pagination topic guide </topics/pagination>`.
``Paginator`` class
===================
-.. class:: Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)
+.. class:: Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True, error_messages=None)
A paginator acts like a sequence of :class:`Page` when using ``len()`` or
iterating it directly.
@@ -56,6 +56,40 @@ For examples, see the :doc:`Pagination topic guide </topics/pagination>`.
``False`` and ``object_list`` is empty, then an ``EmptyPage`` error will
be raised.
+.. attribute:: Paginator.error_messages
+
+ .. versionadded:: 5.0
+
+ The ``error_messages`` argument lets you override the default messages that
+ the paginator will raise. Pass in a dictionary with keys matching the error
+ messages you want to override. Available error message keys are:
+ ``invalid_page``, ``min_page``, and ``no_results``.
+
+ For example, here is the default error message:
+
+ .. code-block:: pycon
+
+ >>> from django.core.paginator import Paginator
+ >>> paginator = Paginator([1, 2, 3], 2)
+ >>> paginator.page(5)
+ Traceback (most recent call last):
+ ...
+ EmptyPage: That page contains no results
+
+ And here is a custom error message:
+
+ .. code-block:: pycon
+
+ >>> paginator = Paginator(
+ ... [1, 2, 3],
+ ... 2,
+ ... error_messages={"no_results": "Page does not exist"},
+ ... )
+ >>> paginator.page(5)
+ Traceback (most recent call last):
+ ...
+ EmptyPage: Page does not exist
+
Methods
-------
diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt
index cc4fb69ee3..0d1e7ffda1 100644
--- a/docs/releases/5.0.txt
+++ b/docs/releases/5.0.txt
@@ -284,6 +284,12 @@ Models
:ref:`Choices classes <field-choices-enum-types>` directly instead of
requiring expansion with the ``choices`` attribute.
+Pagination
+~~~~~~~~~~
+
+* The new :attr:`django.core.paginator.Paginator.error_messages` argument
+ allows customizing the error messages raised by :meth:`.Paginator.page`.
+
Requests and Responses
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/pagination/tests.py b/tests/pagination/tests.py
index a04b6dfe8a..1fa9ea2f02 100644
--- a/tests/pagination/tests.py
+++ b/tests/pagination/tests.py
@@ -128,6 +128,34 @@ class PaginationTests(SimpleTestCase):
with self.assertRaises(PageNotAnInteger):
paginator.validate_number(1.2)
+ def test_error_messages(self):
+ error_messages = {
+ "invalid_page": "Wrong page number",
+ "min_page": "Too small",
+ "no_results": "There is nothing here",
+ }
+ paginator = Paginator([1, 2, 3], 2, error_messages=error_messages)
+ msg = "Wrong page number"
+ with self.assertRaisesMessage(PageNotAnInteger, msg):
+ paginator.validate_number(1.2)
+ msg = "Too small"
+ with self.assertRaisesMessage(EmptyPage, msg):
+ paginator.validate_number(-1)
+ msg = "There is nothing here"
+ with self.assertRaisesMessage(EmptyPage, msg):
+ paginator.validate_number(3)
+
+ error_messages = {"min_page": "Too small"}
+ paginator = Paginator([1, 2, 3], 2, error_messages=error_messages)
+ # Custom message.
+ msg = "Too small"
+ with self.assertRaisesMessage(EmptyPage, msg):
+ paginator.validate_number(-1)
+ # Default message.
+ msg = "That page contains no results"
+ with self.assertRaisesMessage(EmptyPage, msg):
+ paginator.validate_number(3)
+
def test_float_integer_page(self):
paginator = Paginator([1, 2, 3], 2)
self.assertEqual(paginator.validate_number(1.0), 1)