diff options
| author | Claude Paroz <claude@2xlibre.net> | 2012-11-09 19:37:50 +0100 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2012-11-09 19:44:47 +0100 |
| commit | dc95791e61750024a610b6c5cf4d32b7325fcb51 (patch) | |
| tree | f76abd714d76d3f1640ce4626ed3b7755934bb19 | |
| parent | bf35fb600637b020748d05b704a1c0257c7cb63a (diff) | |
[1.5.x] Fixed #19261 -- Delayed Queryset evaluation in paginators
Thanks trbs for the report and the patch.
Backport of 1b307d6c8f from master.
| -rw-r--r-- | django/core/paginator.py | 5 | ||||
| -rw-r--r-- | tests/regressiontests/pagination/tests.py | 22 |
2 files changed, 27 insertions, 0 deletions
diff --git a/django/core/paginator.py b/django/core/paginator.py index 6b0b3542f8..084a29b77f 100644 --- a/django/core/paginator.py +++ b/django/core/paginator.py @@ -1,5 +1,8 @@ from math import ceil +from django.utils import six + + class InvalidPage(Exception): pass @@ -88,6 +91,8 @@ class Page(object): return len(self.object_list) def __getitem__(self, index): + if not isinstance(index, (slice,) + six.integer_types): + raise TypeError # The object_list is converted to a list so that if it was a QuerySet # it won't be a database hit per __getitem__. return list(self.object_list)[index] diff --git a/tests/regressiontests/pagination/tests.py b/tests/regressiontests/pagination/tests.py index a49f9b8fa1..63ccd8f61c 100644 --- a/tests/regressiontests/pagination/tests.py +++ b/tests/regressiontests/pagination/tests.py @@ -266,3 +266,25 @@ class ModelPaginationTests(TestCase): self.assertEqual(1, p.previous_page_number()) self.assertEqual(6, p.start_index()) self.assertEqual(9, p.end_index()) + + def test_page_getitem(self): + """ + Tests proper behaviour of a paginator page __getitem__ (queryset + evaluation, slicing, exception raised). + """ + paginator = Paginator(Article.objects.all(), 5) + p = paginator.page(1) + + # Make sure object_list queryset is not evaluated by an invalid __getitem__ call. + # (this happens from the template engine when using eg: {% page_obj.has_previous %}) + self.assertIsNone(p.object_list._result_cache) + self.assertRaises(TypeError, lambda: p['has_previous']) + self.assertIsNone(p.object_list._result_cache) + + # Make sure slicing the Page object with numbers and slice objects work. + self.assertEqual(p[0], Article.objects.get(headline='Article 1')) + self.assertQuerysetEqual(p[slice(2)], [ + "<Article: Article 1>", + "<Article: Article 2>", + ] + ) |
