2015-02-23 01:53:57 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2013-07-29 19:19:04 +02:00
|
|
|
from __future__ import unicode_literals
|
2011-10-13 23:34:56 +02:00
|
|
|
|
2014-05-19 23:27:09 +02:00
|
|
|
import datetime
|
|
|
|
|
2010-10-18 15:34:47 +02:00
|
|
|
from django.core.exceptions import ImproperlyConfigured
|
2013-12-23 16:01:13 +01:00
|
|
|
from django.test import TestCase, override_settings
|
2012-11-05 08:38:41 +01:00
|
|
|
from django.utils.encoding import force_str
|
2015-01-28 13:35:27 +01:00
|
|
|
from django.views.generic.base import View
|
2010-10-18 15:34:47 +02:00
|
|
|
|
2015-02-23 01:53:57 +01:00
|
|
|
from .models import Artist, Author, Book, Page
|
2011-10-13 23:34:56 +02:00
|
|
|
|
2010-10-18 15:34:47 +02:00
|
|
|
|
2014-04-05 08:04:46 +02:00
|
|
|
@override_settings(ROOT_URLCONF='generic_views.urls')
|
2010-10-18 15:34:47 +02:00
|
|
|
class ListViewTests(TestCase):
|
2015-02-23 01:53:57 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpTestData(cls):
|
|
|
|
cls.artist1 = Artist.objects.create(name='Rene Magritte')
|
|
|
|
cls.author1 = Author.objects.create(name='Roberto Bolaño', slug='roberto-bolano')
|
|
|
|
cls.author2 = Author.objects.create(name='Scott Rosenberg', slug='scott-rosenberg')
|
|
|
|
cls.book1 = Book.objects.create(name='2066', slug='2066', pages=800, pubdate=datetime.date(2008, 10, 1))
|
|
|
|
cls.book1.authors.add(cls.author1)
|
|
|
|
cls.book2 = Book.objects.create(
|
|
|
|
name='Dreaming in Code', slug='dreaming-in-code', pages=300, pubdate=datetime.date(2006, 5, 1)
|
|
|
|
)
|
|
|
|
cls.page1 = Page.objects.create(
|
|
|
|
content='I was once bitten by a moose.', template='generic_views/page_template.html'
|
|
|
|
)
|
2010-10-18 15:34:47 +02:00
|
|
|
|
|
|
|
def test_items(self):
|
|
|
|
res = self.client.get('/list/dict/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/list.html')
|
|
|
|
self.assertEqual(res.context['object_list'][0]['first'], 'John')
|
|
|
|
|
|
|
|
def test_queryset(self):
|
|
|
|
res = self.client.get('/list/authors/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2013-05-21 11:42:15 +02:00
|
|
|
self.assertIsInstance(res.context['view'], View)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertIsNone(res.context['paginator'])
|
|
|
|
self.assertIsNone(res.context['page_obj'])
|
|
|
|
self.assertFalse(res.context['is_paginated'])
|
2010-10-18 15:34:47 +02:00
|
|
|
|
|
|
|
def test_paginated_queryset(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertEqual(len(res.context['object_list']), 30)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertTrue(res.context['is_paginated'])
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertEqual(res.context['page_obj'].number, 1)
|
|
|
|
self.assertEqual(res.context['paginator'].num_pages, 4)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertEqual(res.context['author_list'][0].name, 'Author 00')
|
|
|
|
self.assertEqual(list(res.context['author_list'])[-1].name, 'Author 29')
|
2010-10-18 15:34:47 +02:00
|
|
|
|
|
|
|
def test_paginated_queryset_shortdata(self):
|
2011-01-08 14:15:44 +01:00
|
|
|
# Test that short datasets ALSO result in a paginated view.
|
2010-10-18 15:34:47 +02:00
|
|
|
res = self.client.get('/list/authors/paginated/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2011-01-08 14:15:44 +01:00
|
|
|
self.assertEqual(res.context['page_obj'].number, 1)
|
|
|
|
self.assertEqual(res.context['paginator'].num_pages, 1)
|
2011-03-15 09:24:31 +01:00
|
|
|
self.assertFalse(res.context['is_paginated'])
|
2010-10-18 15:34:47 +02:00
|
|
|
|
|
|
|
def test_paginated_get_page_by_query_string(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/', {'page': '2'})
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertEqual(len(res.context['object_list']), 30)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
|
|
|
self.assertEqual(res.context['author_list'][0].name, 'Author 30')
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertEqual(res.context['page_obj'].number, 2)
|
|
|
|
|
|
|
|
def test_paginated_get_last_page_by_query_string(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/', {'page': 'last'})
|
|
|
|
self.assertEqual(res.status_code, 200)
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertEqual(len(res.context['object_list']), 10)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
|
|
|
self.assertEqual(res.context['author_list'][0].name, 'Author 90')
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertEqual(res.context['page_obj'].number, 4)
|
|
|
|
|
|
|
|
def test_paginated_get_page_by_urlvar(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/3/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertEqual(len(res.context['object_list']), 30)
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
|
|
|
self.assertEqual(res.context['author_list'][0].name, 'Author 60')
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertEqual(res.context['page_obj'].number, 3)
|
|
|
|
|
|
|
|
def test_paginated_page_out_of_range(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/42/')
|
|
|
|
self.assertEqual(res.status_code, 404)
|
|
|
|
|
|
|
|
def test_paginated_invalid_page(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/?page=frog')
|
|
|
|
self.assertEqual(res.status_code, 404)
|
|
|
|
|
2010-12-05 05:32:36 +01:00
|
|
|
def test_paginated_custom_paginator_class(self):
|
|
|
|
self._make_authors(7)
|
|
|
|
res = self.client.get('/list/authors/paginated/custom_class/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
2011-01-08 14:15:44 +01:00
|
|
|
self.assertEqual(res.context['paginator'].num_pages, 1)
|
2010-12-05 05:32:36 +01:00
|
|
|
# Custom pagination allows for 2 orphans on a page size of 5
|
|
|
|
self.assertEqual(len(res.context['object_list']), 7)
|
|
|
|
|
2012-10-25 14:19:53 +02:00
|
|
|
def test_paginated_custom_page_kwarg(self):
|
|
|
|
self._make_authors(100)
|
|
|
|
res = self.client.get('/list/authors/paginated/custom_page_kwarg/', {'pagina': '2'})
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
|
|
|
self.assertEqual(len(res.context['object_list']), 30)
|
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
|
|
|
self.assertEqual(res.context['author_list'][0].name, 'Author 30')
|
|
|
|
self.assertEqual(res.context['page_obj'].number, 2)
|
|
|
|
|
2010-12-05 05:32:36 +01:00
|
|
|
def test_paginated_custom_paginator_constructor(self):
|
|
|
|
self._make_authors(7)
|
|
|
|
res = self.client.get('/list/authors/paginated/custom_constructor/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
# Custom pagination allows for 2 orphans on a page size of 5
|
|
|
|
self.assertEqual(len(res.context['object_list']), 7)
|
|
|
|
|
2012-11-21 04:45:38 +01:00
|
|
|
def test_paginated_orphaned_queryset(self):
|
|
|
|
self._make_authors(92)
|
|
|
|
res = self.client.get('/list/authors/paginated-orphaned/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(res.context['page_obj'].number, 1)
|
|
|
|
res = self.client.get(
|
|
|
|
'/list/authors/paginated-orphaned/', {'page': 'last'})
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(res.context['page_obj'].number, 3)
|
|
|
|
res = self.client.get(
|
|
|
|
'/list/authors/paginated-orphaned/', {'page': '3'})
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(res.context['page_obj'].number, 3)
|
|
|
|
res = self.client.get(
|
|
|
|
'/list/authors/paginated-orphaned/', {'page': '4'})
|
|
|
|
self.assertEqual(res.status_code, 404)
|
|
|
|
|
2010-12-09 03:34:14 +01:00
|
|
|
def test_paginated_non_queryset(self):
|
|
|
|
res = self.client.get('/list/dict/paginated/')
|
2012-11-21 04:45:38 +01:00
|
|
|
|
2010-12-09 03:34:14 +01:00
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(len(res.context['object_list']), 1)
|
|
|
|
|
2011-01-03 14:15:58 +01:00
|
|
|
def test_verbose_name(self):
|
|
|
|
res = self.client.get('/list/artists/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertTemplateUsed(res, 'generic_views/list.html')
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Artist.objects.all()))
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['artist_list'], res.context['object_list'])
|
2011-01-03 14:15:58 +01:00
|
|
|
self.assertIsNone(res.context['paginator'])
|
|
|
|
self.assertIsNone(res.context['page_obj'])
|
|
|
|
self.assertFalse(res.context['is_paginated'])
|
|
|
|
|
2010-10-18 15:34:47 +02:00
|
|
|
def test_allow_empty_false(self):
|
|
|
|
res = self.client.get('/list/authors/notempty/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
Author.objects.all().delete()
|
|
|
|
res = self.client.get('/list/authors/notempty/')
|
|
|
|
self.assertEqual(res.status_code, 404)
|
|
|
|
|
|
|
|
def test_template_name(self):
|
|
|
|
res = self.client.get('/list/authors/template_name/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertTemplateUsed(res, 'generic_views/list.html')
|
|
|
|
|
|
|
|
def test_template_name_suffix(self):
|
|
|
|
res = self.client.get('/list/authors/template_name_suffix/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2011-02-14 14:04:51 +01:00
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_objects.html')
|
|
|
|
|
|
|
|
def test_context_object_name(self):
|
|
|
|
res = self.client.get('/list/authors/context_object_name/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertNotIn('authors', res.context)
|
|
|
|
self.assertIs(res.context['author_list'], res.context['object_list'])
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
|
|
|
|
|
|
|
def test_duplicate_context_object_name(self):
|
|
|
|
res = self.client.get('/list/authors/dupe_context_object_name/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(list(res.context['object_list']), list(Author.objects.all()))
|
2010-10-28 04:58:28 +02:00
|
|
|
self.assertNotIn('authors', res.context)
|
|
|
|
self.assertNotIn('author_list', res.context)
|
2010-10-18 15:34:47 +02:00
|
|
|
self.assertTemplateUsed(res, 'generic_views/author_list.html')
|
|
|
|
|
|
|
|
def test_missing_items(self):
|
2016-01-17 12:26:39 +01:00
|
|
|
with self.assertRaises(ImproperlyConfigured):
|
|
|
|
self.client.get('/list/authors/invalid/')
|
2010-10-18 15:34:47 +02:00
|
|
|
|
2012-05-17 13:29:52 +02:00
|
|
|
def test_paginated_list_view_does_not_load_entire_table(self):
|
|
|
|
# Regression test for #17535
|
|
|
|
self._make_authors(3)
|
|
|
|
# 1 query for authors
|
|
|
|
with self.assertNumQueries(1):
|
|
|
|
self.client.get('/list/authors/notempty/')
|
|
|
|
# same as above + 1 query to test if authors exist + 1 query for pagination
|
|
|
|
with self.assertNumQueries(3):
|
|
|
|
self.client.get('/list/authors/notempty/paginated/')
|
|
|
|
|
2014-05-19 23:27:09 +02:00
|
|
|
def test_explicitly_ordered_list_view(self):
|
|
|
|
Book.objects.create(name="Zebras for Dummies", pages=800, pubdate=datetime.date(2006, 9, 1))
|
|
|
|
res = self.client.get('/list/books/sorted/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(res.context['object_list'][0].name, '2066')
|
|
|
|
self.assertEqual(res.context['object_list'][1].name, 'Dreaming in Code')
|
|
|
|
self.assertEqual(res.context['object_list'][2].name, 'Zebras for Dummies')
|
|
|
|
|
|
|
|
res = self.client.get('/list/books/sortedbypagesandnamedec/')
|
|
|
|
self.assertEqual(res.status_code, 200)
|
|
|
|
self.assertEqual(res.context['object_list'][0].name, 'Dreaming in Code')
|
|
|
|
self.assertEqual(res.context['object_list'][1].name, 'Zebras for Dummies')
|
|
|
|
self.assertEqual(res.context['object_list'][2].name, '2066')
|
|
|
|
|
2012-11-05 00:46:30 +01:00
|
|
|
@override_settings(DEBUG=True)
|
|
|
|
def test_paginated_list_view_returns_useful_message_on_invalid_page(self):
|
|
|
|
# test for #19240
|
|
|
|
# tests that source exception's message is included in page
|
|
|
|
self._make_authors(1)
|
|
|
|
res = self.client.get('/list/authors/paginated/2/')
|
|
|
|
self.assertEqual(res.status_code, 404)
|
2016-04-08 04:04:45 +02:00
|
|
|
self.assertEqual(force_str(res.context.get('reason')), "Invalid page (2): That page contains no results")
|
2012-11-05 00:46:30 +01:00
|
|
|
|
2010-10-18 15:34:47 +02:00
|
|
|
def _make_authors(self, n):
|
|
|
|
Author.objects.all().delete()
|
|
|
|
for i in range(n):
|
|
|
|
Author.objects.create(name='Author %02i' % i, slug='a%s' % i)
|