list.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. from __future__ import absolute_import
  2. from django.core.exceptions import ImproperlyConfigured
  3. from django.test import TestCase
  4. from django.test.utils import override_settings
  5. from django.views.generic.base import View
  6. from django.utils.encoding import force_str
  7. from .models import Author, Artist
  8. class ListViewTests(TestCase):
  9. fixtures = ['generic-views-test-data.json']
  10. urls = 'regressiontests.generic_views.urls'
  11. def test_items(self):
  12. res = self.client.get('/list/dict/')
  13. self.assertEqual(res.status_code, 200)
  14. self.assertTemplateUsed(res, 'generic_views/list.html')
  15. self.assertEqual(res.context['object_list'][0]['first'], 'John')
  16. def test_queryset(self):
  17. res = self.client.get('/list/authors/')
  18. self.assertEqual(res.status_code, 200)
  19. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  20. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  21. self.assertTrue(isinstance(res.context['view'], View))
  22. self.assertIs(res.context['author_list'], res.context['object_list'])
  23. self.assertIsNone(res.context['paginator'])
  24. self.assertIsNone(res.context['page_obj'])
  25. self.assertFalse(res.context['is_paginated'])
  26. def test_paginated_queryset(self):
  27. self._make_authors(100)
  28. res = self.client.get('/list/authors/paginated/')
  29. self.assertEqual(res.status_code, 200)
  30. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  31. self.assertEqual(len(res.context['object_list']), 30)
  32. self.assertIs(res.context['author_list'], res.context['object_list'])
  33. self.assertTrue(res.context['is_paginated'])
  34. self.assertEqual(res.context['page_obj'].number, 1)
  35. self.assertEqual(res.context['paginator'].num_pages, 4)
  36. self.assertEqual(res.context['author_list'][0].name, 'Author 00')
  37. self.assertEqual(list(res.context['author_list'])[-1].name, 'Author 29')
  38. def test_paginated_queryset_shortdata(self):
  39. # Test that short datasets ALSO result in a paginated view.
  40. res = self.client.get('/list/authors/paginated/')
  41. self.assertEqual(res.status_code, 200)
  42. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  43. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  44. self.assertIs(res.context['author_list'], res.context['object_list'])
  45. self.assertEqual(res.context['page_obj'].number, 1)
  46. self.assertEqual(res.context['paginator'].num_pages, 1)
  47. self.assertFalse(res.context['is_paginated'])
  48. def test_paginated_get_page_by_query_string(self):
  49. self._make_authors(100)
  50. res = self.client.get('/list/authors/paginated/', {'page': '2'})
  51. self.assertEqual(res.status_code, 200)
  52. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  53. self.assertEqual(len(res.context['object_list']), 30)
  54. self.assertIs(res.context['author_list'], res.context['object_list'])
  55. self.assertEqual(res.context['author_list'][0].name, 'Author 30')
  56. self.assertEqual(res.context['page_obj'].number, 2)
  57. def test_paginated_get_last_page_by_query_string(self):
  58. self._make_authors(100)
  59. res = self.client.get('/list/authors/paginated/', {'page': 'last'})
  60. self.assertEqual(res.status_code, 200)
  61. self.assertEqual(len(res.context['object_list']), 10)
  62. self.assertIs(res.context['author_list'], res.context['object_list'])
  63. self.assertEqual(res.context['author_list'][0].name, 'Author 90')
  64. self.assertEqual(res.context['page_obj'].number, 4)
  65. def test_paginated_get_page_by_urlvar(self):
  66. self._make_authors(100)
  67. res = self.client.get('/list/authors/paginated/3/')
  68. self.assertEqual(res.status_code, 200)
  69. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  70. self.assertEqual(len(res.context['object_list']), 30)
  71. self.assertIs(res.context['author_list'], res.context['object_list'])
  72. self.assertEqual(res.context['author_list'][0].name, 'Author 60')
  73. self.assertEqual(res.context['page_obj'].number, 3)
  74. def test_paginated_page_out_of_range(self):
  75. self._make_authors(100)
  76. res = self.client.get('/list/authors/paginated/42/')
  77. self.assertEqual(res.status_code, 404)
  78. def test_paginated_invalid_page(self):
  79. self._make_authors(100)
  80. res = self.client.get('/list/authors/paginated/?page=frog')
  81. self.assertEqual(res.status_code, 404)
  82. def test_paginated_custom_paginator_class(self):
  83. self._make_authors(7)
  84. res = self.client.get('/list/authors/paginated/custom_class/')
  85. self.assertEqual(res.status_code, 200)
  86. self.assertEqual(res.context['paginator'].num_pages, 1)
  87. # Custom pagination allows for 2 orphans on a page size of 5
  88. self.assertEqual(len(res.context['object_list']), 7)
  89. def test_paginated_custom_page_kwarg(self):
  90. self._make_authors(100)
  91. res = self.client.get('/list/authors/paginated/custom_page_kwarg/', {'pagina': '2'})
  92. self.assertEqual(res.status_code, 200)
  93. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  94. self.assertEqual(len(res.context['object_list']), 30)
  95. self.assertIs(res.context['author_list'], res.context['object_list'])
  96. self.assertEqual(res.context['author_list'][0].name, 'Author 30')
  97. self.assertEqual(res.context['page_obj'].number, 2)
  98. def test_paginated_custom_paginator_constructor(self):
  99. self._make_authors(7)
  100. res = self.client.get('/list/authors/paginated/custom_constructor/')
  101. self.assertEqual(res.status_code, 200)
  102. # Custom pagination allows for 2 orphans on a page size of 5
  103. self.assertEqual(len(res.context['object_list']), 7)
  104. def test_paginated_orphaned_queryset(self):
  105. self._make_authors(92)
  106. res = self.client.get('/list/authors/paginated-orphaned/')
  107. self.assertEqual(res.status_code, 200)
  108. self.assertEqual(res.context['page_obj'].number, 1)
  109. res = self.client.get(
  110. '/list/authors/paginated-orphaned/', {'page': 'last'})
  111. self.assertEqual(res.status_code, 200)
  112. self.assertEqual(res.context['page_obj'].number, 3)
  113. res = self.client.get(
  114. '/list/authors/paginated-orphaned/', {'page': '3'})
  115. self.assertEqual(res.status_code, 200)
  116. self.assertEqual(res.context['page_obj'].number, 3)
  117. res = self.client.get(
  118. '/list/authors/paginated-orphaned/', {'page': '4'})
  119. self.assertEqual(res.status_code, 404)
  120. def test_paginated_non_queryset(self):
  121. res = self.client.get('/list/dict/paginated/')
  122. self.assertEqual(res.status_code, 200)
  123. self.assertEqual(len(res.context['object_list']), 1)
  124. def test_verbose_name(self):
  125. res = self.client.get('/list/artists/')
  126. self.assertEqual(res.status_code, 200)
  127. self.assertTemplateUsed(res, 'generic_views/list.html')
  128. self.assertEqual(list(res.context['object_list']), list(Artist.objects.all()))
  129. self.assertIs(res.context['artist_list'], res.context['object_list'])
  130. self.assertIsNone(res.context['paginator'])
  131. self.assertIsNone(res.context['page_obj'])
  132. self.assertFalse(res.context['is_paginated'])
  133. def test_allow_empty_false(self):
  134. res = self.client.get('/list/authors/notempty/')
  135. self.assertEqual(res.status_code, 200)
  136. Author.objects.all().delete()
  137. res = self.client.get('/list/authors/notempty/')
  138. self.assertEqual(res.status_code, 404)
  139. def test_template_name(self):
  140. res = self.client.get('/list/authors/template_name/')
  141. self.assertEqual(res.status_code, 200)
  142. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  143. self.assertIs(res.context['author_list'], res.context['object_list'])
  144. self.assertTemplateUsed(res, 'generic_views/list.html')
  145. def test_template_name_suffix(self):
  146. res = self.client.get('/list/authors/template_name_suffix/')
  147. self.assertEqual(res.status_code, 200)
  148. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  149. self.assertIs(res.context['author_list'], res.context['object_list'])
  150. self.assertTemplateUsed(res, 'generic_views/author_objects.html')
  151. def test_context_object_name(self):
  152. res = self.client.get('/list/authors/context_object_name/')
  153. self.assertEqual(res.status_code, 200)
  154. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  155. self.assertNotIn('authors', res.context)
  156. self.assertIs(res.context['author_list'], res.context['object_list'])
  157. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  158. def test_duplicate_context_object_name(self):
  159. res = self.client.get('/list/authors/dupe_context_object_name/')
  160. self.assertEqual(res.status_code, 200)
  161. self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
  162. self.assertNotIn('authors', res.context)
  163. self.assertNotIn('author_list', res.context)
  164. self.assertTemplateUsed(res, 'generic_views/author_list.html')
  165. def test_missing_items(self):
  166. self.assertRaises(ImproperlyConfigured, self.client.get, '/list/authors/invalid/')
  167. def test_paginated_list_view_does_not_load_entire_table(self):
  168. # Regression test for #17535
  169. self._make_authors(3)
  170. # 1 query for authors
  171. with self.assertNumQueries(1):
  172. self.client.get('/list/authors/notempty/')
  173. # same as above + 1 query to test if authors exist + 1 query for pagination
  174. with self.assertNumQueries(3):
  175. self.client.get('/list/authors/notempty/paginated/')
  176. @override_settings(DEBUG=True)
  177. def test_paginated_list_view_returns_useful_message_on_invalid_page(self):
  178. # test for #19240
  179. # tests that source exception's message is included in page
  180. self._make_authors(1)
  181. res = self.client.get('/list/authors/paginated/2/')
  182. self.assertEqual(res.status_code, 404)
  183. self.assertEqual(force_str(res.context.get('reason')),
  184. "Invalid page (2): That page contains no results")
  185. def _make_authors(self, n):
  186. Author.objects.all().delete()
  187. for i in range(n):
  188. Author.objects.create(name='Author %02i' % i, slug='a%s' % i)