diff --git a/django/core/paginator.py b/django/core/paginator.py index 2933f802c6..2686957af0 100644 --- a/django/core/paginator.py +++ b/django/core/paginator.py @@ -96,10 +96,16 @@ class Paginator: """ Warn if self.object_list is unordered (typically a QuerySet). """ - if hasattr(self.object_list, 'ordered') and not self.object_list.ordered: + ordered = getattr(self.object_list, 'ordered', None) + if ordered is not None and not ordered: + obj_list_repr = ( + '{} {}'.format(self.object_list.model, self.object_list.__class__.__name__) + if hasattr(self.object_list, 'model') + else '{!r}'.format(self.object_list) + ) warnings.warn( 'Pagination may yield inconsistent results with an unordered ' - 'object_list: {!r}'.format(self.object_list), + 'object_list: {}.'.format(obj_list_repr), UnorderedObjectListWarning, stacklevel=3 ) diff --git a/docs/releases/1.11.3.txt b/docs/releases/1.11.3.txt index 33645d05b3..6afe77e8bb 100644 --- a/docs/releases/1.11.3.txt +++ b/docs/releases/1.11.3.txt @@ -32,3 +32,6 @@ Bugfixes * Fixed ``QuerySet.union()``, ``intersection()``, and ``difference()`` when combining with an ``EmptyQuerySet`` (:ticket:`28293`). + +* Prevented ``Paginator``’s unordered object list warning from evaluating a + ``QuerySet`` (:ticket:`28284`). diff --git a/tests/pagination/tests.py b/tests/pagination/tests.py index 30fa310dc0..9319666597 100644 --- a/tests/pagination/tests.py +++ b/tests/pagination/tests.py @@ -328,11 +328,25 @@ class ModelPaginationTests(TestCase): warning = warns[0] self.assertEqual(str(warning.message), ( "Pagination may yield inconsistent results with an unordered " - "object_list: , " - ", , , " - ", , , " - ", ]>" + "object_list: QuerySet." )) # The warning points at the Paginator caller (i.e. the stacklevel # is appropriate). self.assertEqual(warning.filename, __file__) + + def test_paginating_unordered_object_list_raises_warning(self): + """ + Unordered object list warning with an object that has an orderd + attribute but not a model attribute. + """ + class ObjectList(): + ordered = False + object_list = ObjectList() + with warnings.catch_warnings(record=True) as warns: + warnings.filterwarnings('always', category=UnorderedObjectListWarning) + Paginator(object_list, 5) + self.assertEqual(len(warns), 1) + self.assertEqual(str(warns[0].message), ( + "Pagination may yield inconsistent results with an unordered " + "object_list: {!r}.".format(object_list) + ))