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