1. import datetime
    
  2. 
    
  3. from django.core.exceptions import ImproperlyConfigured
    
  4. from django.test import TestCase, override_settings
    
  5. from django.views.generic.base import View
    
  6. 
    
  7. from .models import Artist, Author, Book, Page
    
  8. 
    
  9. 
    
  10. @override_settings(ROOT_URLCONF="generic_views.urls")
    
  11. class ListViewTests(TestCase):
    
  12.     @classmethod
    
  13.     def setUpTestData(cls):
    
  14.         cls.artist1 = Artist.objects.create(name="Rene Magritte")
    
  15.         cls.author1 = Author.objects.create(
    
  16.             name="Roberto BolaƱo", slug="roberto-bolano"
    
  17.         )
    
  18.         cls.author2 = Author.objects.create(
    
  19.             name="Scott Rosenberg", slug="scott-rosenberg"
    
  20.         )
    
  21.         cls.book1 = Book.objects.create(
    
  22.             name="2066", slug="2066", pages=800, pubdate=datetime.date(2008, 10, 1)
    
  23.         )
    
  24.         cls.book1.authors.add(cls.author1)
    
  25.         cls.book2 = Book.objects.create(
    
  26.             name="Dreaming in Code",
    
  27.             slug="dreaming-in-code",
    
  28.             pages=300,
    
  29.             pubdate=datetime.date(2006, 5, 1),
    
  30.         )
    
  31.         cls.page1 = Page.objects.create(
    
  32.             content="I was once bitten by a moose.",
    
  33.             template="generic_views/page_template.html",
    
  34.         )
    
  35. 
    
  36.     def test_items(self):
    
  37.         res = self.client.get("/list/dict/")
    
  38.         self.assertEqual(res.status_code, 200)
    
  39.         self.assertTemplateUsed(res, "generic_views/list.html")
    
  40.         self.assertEqual(res.context["object_list"][0]["first"], "John")
    
  41. 
    
  42.     def test_queryset(self):
    
  43.         res = self.client.get("/list/authors/")
    
  44.         self.assertEqual(res.status_code, 200)
    
  45.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  46.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  47.         self.assertIsInstance(res.context["view"], View)
    
  48.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  49.         self.assertIsNone(res.context["paginator"])
    
  50.         self.assertIsNone(res.context["page_obj"])
    
  51.         self.assertFalse(res.context["is_paginated"])
    
  52. 
    
  53.     def test_paginated_queryset(self):
    
  54.         self._make_authors(100)
    
  55.         res = self.client.get("/list/authors/paginated/")
    
  56.         self.assertEqual(res.status_code, 200)
    
  57.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  58.         self.assertEqual(len(res.context["object_list"]), 30)
    
  59.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  60.         self.assertTrue(res.context["is_paginated"])
    
  61.         self.assertEqual(res.context["page_obj"].number, 1)
    
  62.         self.assertEqual(res.context["paginator"].num_pages, 4)
    
  63.         self.assertEqual(res.context["author_list"][0].name, "Author 00")
    
  64.         self.assertEqual(list(res.context["author_list"])[-1].name, "Author 29")
    
  65. 
    
  66.     def test_paginated_queryset_shortdata(self):
    
  67.         # Short datasets also result in a paginated view.
    
  68.         res = self.client.get("/list/authors/paginated/")
    
  69.         self.assertEqual(res.status_code, 200)
    
  70.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  71.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  72.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  73.         self.assertEqual(res.context["page_obj"].number, 1)
    
  74.         self.assertEqual(res.context["paginator"].num_pages, 1)
    
  75.         self.assertFalse(res.context["is_paginated"])
    
  76. 
    
  77.     def test_paginated_get_page_by_query_string(self):
    
  78.         self._make_authors(100)
    
  79.         res = self.client.get("/list/authors/paginated/", {"page": "2"})
    
  80.         self.assertEqual(res.status_code, 200)
    
  81.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  82.         self.assertEqual(len(res.context["object_list"]), 30)
    
  83.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  84.         self.assertEqual(res.context["author_list"][0].name, "Author 30")
    
  85.         self.assertEqual(res.context["page_obj"].number, 2)
    
  86. 
    
  87.     def test_paginated_get_last_page_by_query_string(self):
    
  88.         self._make_authors(100)
    
  89.         res = self.client.get("/list/authors/paginated/", {"page": "last"})
    
  90.         self.assertEqual(res.status_code, 200)
    
  91.         self.assertEqual(len(res.context["object_list"]), 10)
    
  92.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  93.         self.assertEqual(res.context["author_list"][0].name, "Author 90")
    
  94.         self.assertEqual(res.context["page_obj"].number, 4)
    
  95. 
    
  96.     def test_paginated_get_page_by_urlvar(self):
    
  97.         self._make_authors(100)
    
  98.         res = self.client.get("/list/authors/paginated/3/")
    
  99.         self.assertEqual(res.status_code, 200)
    
  100.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  101.         self.assertEqual(len(res.context["object_list"]), 30)
    
  102.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  103.         self.assertEqual(res.context["author_list"][0].name, "Author 60")
    
  104.         self.assertEqual(res.context["page_obj"].number, 3)
    
  105. 
    
  106.     def test_paginated_page_out_of_range(self):
    
  107.         self._make_authors(100)
    
  108.         res = self.client.get("/list/authors/paginated/42/")
    
  109.         self.assertEqual(res.status_code, 404)
    
  110. 
    
  111.     def test_paginated_invalid_page(self):
    
  112.         self._make_authors(100)
    
  113.         res = self.client.get("/list/authors/paginated/?page=frog")
    
  114.         self.assertEqual(res.status_code, 404)
    
  115. 
    
  116.     def test_paginated_custom_paginator_class(self):
    
  117.         self._make_authors(7)
    
  118.         res = self.client.get("/list/authors/paginated/custom_class/")
    
  119.         self.assertEqual(res.status_code, 200)
    
  120.         self.assertEqual(res.context["paginator"].num_pages, 1)
    
  121.         # Custom pagination allows for 2 orphans on a page size of 5
    
  122.         self.assertEqual(len(res.context["object_list"]), 7)
    
  123. 
    
  124.     def test_paginated_custom_page_kwarg(self):
    
  125.         self._make_authors(100)
    
  126.         res = self.client.get(
    
  127.             "/list/authors/paginated/custom_page_kwarg/", {"pagina": "2"}
    
  128.         )
    
  129.         self.assertEqual(res.status_code, 200)
    
  130.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  131.         self.assertEqual(len(res.context["object_list"]), 30)
    
  132.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  133.         self.assertEqual(res.context["author_list"][0].name, "Author 30")
    
  134.         self.assertEqual(res.context["page_obj"].number, 2)
    
  135. 
    
  136.     def test_paginated_custom_paginator_constructor(self):
    
  137.         self._make_authors(7)
    
  138.         res = self.client.get("/list/authors/paginated/custom_constructor/")
    
  139.         self.assertEqual(res.status_code, 200)
    
  140.         # Custom pagination allows for 2 orphans on a page size of 5
    
  141.         self.assertEqual(len(res.context["object_list"]), 7)
    
  142. 
    
  143.     def test_paginated_orphaned_queryset(self):
    
  144.         self._make_authors(92)
    
  145.         res = self.client.get("/list/authors/paginated-orphaned/")
    
  146.         self.assertEqual(res.status_code, 200)
    
  147.         self.assertEqual(res.context["page_obj"].number, 1)
    
  148.         res = self.client.get("/list/authors/paginated-orphaned/", {"page": "last"})
    
  149.         self.assertEqual(res.status_code, 200)
    
  150.         self.assertEqual(res.context["page_obj"].number, 3)
    
  151.         res = self.client.get("/list/authors/paginated-orphaned/", {"page": "3"})
    
  152.         self.assertEqual(res.status_code, 200)
    
  153.         self.assertEqual(res.context["page_obj"].number, 3)
    
  154.         res = self.client.get("/list/authors/paginated-orphaned/", {"page": "4"})
    
  155.         self.assertEqual(res.status_code, 404)
    
  156. 
    
  157.     def test_paginated_non_queryset(self):
    
  158.         res = self.client.get("/list/dict/paginated/")
    
  159. 
    
  160.         self.assertEqual(res.status_code, 200)
    
  161.         self.assertEqual(len(res.context["object_list"]), 1)
    
  162. 
    
  163.     def test_verbose_name(self):
    
  164.         res = self.client.get("/list/artists/")
    
  165.         self.assertEqual(res.status_code, 200)
    
  166.         self.assertTemplateUsed(res, "generic_views/list.html")
    
  167.         self.assertEqual(list(res.context["object_list"]), list(Artist.objects.all()))
    
  168.         self.assertIs(res.context["artist_list"], res.context["object_list"])
    
  169.         self.assertIsNone(res.context["paginator"])
    
  170.         self.assertIsNone(res.context["page_obj"])
    
  171.         self.assertFalse(res.context["is_paginated"])
    
  172. 
    
  173.     def test_allow_empty_false(self):
    
  174.         res = self.client.get("/list/authors/notempty/")
    
  175.         self.assertEqual(res.status_code, 200)
    
  176.         Author.objects.all().delete()
    
  177.         res = self.client.get("/list/authors/notempty/")
    
  178.         self.assertEqual(res.status_code, 404)
    
  179. 
    
  180.     def test_template_name(self):
    
  181.         res = self.client.get("/list/authors/template_name/")
    
  182.         self.assertEqual(res.status_code, 200)
    
  183.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  184.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  185.         self.assertTemplateUsed(res, "generic_views/list.html")
    
  186. 
    
  187.     def test_template_name_suffix(self):
    
  188.         res = self.client.get("/list/authors/template_name_suffix/")
    
  189.         self.assertEqual(res.status_code, 200)
    
  190.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  191.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  192.         self.assertTemplateUsed(res, "generic_views/author_objects.html")
    
  193. 
    
  194.     def test_context_object_name(self):
    
  195.         res = self.client.get("/list/authors/context_object_name/")
    
  196.         self.assertEqual(res.status_code, 200)
    
  197.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  198.         self.assertNotIn("authors", res.context)
    
  199.         self.assertIs(res.context["author_list"], res.context["object_list"])
    
  200.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  201. 
    
  202.     def test_duplicate_context_object_name(self):
    
  203.         res = self.client.get("/list/authors/dupe_context_object_name/")
    
  204.         self.assertEqual(res.status_code, 200)
    
  205.         self.assertEqual(list(res.context["object_list"]), list(Author.objects.all()))
    
  206.         self.assertNotIn("authors", res.context)
    
  207.         self.assertNotIn("author_list", res.context)
    
  208.         self.assertTemplateUsed(res, "generic_views/author_list.html")
    
  209. 
    
  210.     def test_missing_items(self):
    
  211.         msg = (
    
  212.             "AuthorList is missing a QuerySet. Define AuthorList.model, "
    
  213.             "AuthorList.queryset, or override AuthorList.get_queryset()."
    
  214.         )
    
  215.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  216.             self.client.get("/list/authors/invalid/")
    
  217. 
    
  218.     def test_invalid_get_queryset(self):
    
  219.         msg = (
    
  220.             "AuthorListGetQuerysetReturnsNone requires either a 'template_name' "
    
  221.             "attribute or a get_queryset() method that returns a QuerySet."
    
  222.         )
    
  223.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  224.             self.client.get("/list/authors/get_queryset/")
    
  225. 
    
  226.     def test_paginated_list_view_does_not_load_entire_table(self):
    
  227.         # Regression test for #17535
    
  228.         self._make_authors(3)
    
  229.         # 1 query for authors
    
  230.         with self.assertNumQueries(1):
    
  231.             self.client.get("/list/authors/notempty/")
    
  232.         # same as above + 1 query to test if authors exist + 1 query for pagination
    
  233.         with self.assertNumQueries(3):
    
  234.             self.client.get("/list/authors/notempty/paginated/")
    
  235. 
    
  236.     def test_explicitly_ordered_list_view(self):
    
  237.         Book.objects.create(
    
  238.             name="Zebras for Dummies", pages=800, pubdate=datetime.date(2006, 9, 1)
    
  239.         )
    
  240.         res = self.client.get("/list/books/sorted/")
    
  241.         self.assertEqual(res.status_code, 200)
    
  242.         self.assertEqual(res.context["object_list"][0].name, "2066")
    
  243.         self.assertEqual(res.context["object_list"][1].name, "Dreaming in Code")
    
  244.         self.assertEqual(res.context["object_list"][2].name, "Zebras for Dummies")
    
  245. 
    
  246.         res = self.client.get("/list/books/sortedbypagesandnamedec/")
    
  247.         self.assertEqual(res.status_code, 200)
    
  248.         self.assertEqual(res.context["object_list"][0].name, "Dreaming in Code")
    
  249.         self.assertEqual(res.context["object_list"][1].name, "Zebras for Dummies")
    
  250.         self.assertEqual(res.context["object_list"][2].name, "2066")
    
  251. 
    
  252.     @override_settings(DEBUG=True)
    
  253.     def test_paginated_list_view_returns_useful_message_on_invalid_page(self):
    
  254.         # test for #19240
    
  255.         # tests that source exception's message is included in page
    
  256.         self._make_authors(1)
    
  257.         res = self.client.get("/list/authors/paginated/2/")
    
  258.         self.assertEqual(res.status_code, 404)
    
  259.         self.assertEqual(
    
  260.             res.context.get("reason"), "Invalid page (2): That page contains no results"
    
  261.         )
    
  262. 
    
  263.     def _make_authors(self, n):
    
  264.         Author.objects.all().delete()
    
  265.         for i in range(n):
    
  266.             Author.objects.create(name="Author %02i" % i, slug="a%s" % i)