1. import time
    
  2. 
    
  3. from django.core.exceptions import ImproperlyConfigured
    
  4. from django.http import HttpResponse
    
  5. from django.test import RequestFactory, SimpleTestCase, override_settings
    
  6. from django.test.utils import require_jinja2
    
  7. from django.urls import resolve
    
  8. from django.views.generic import RedirectView, TemplateView, View
    
  9. 
    
  10. from . import views
    
  11. 
    
  12. 
    
  13. class SimpleView(View):
    
  14.     """
    
  15.     A simple view with a docstring.
    
  16.     """
    
  17. 
    
  18.     def get(self, request):
    
  19.         return HttpResponse("This is a simple view")
    
  20. 
    
  21. 
    
  22. class SimplePostView(SimpleView):
    
  23.     post = SimpleView.get
    
  24. 
    
  25. 
    
  26. class PostOnlyView(View):
    
  27.     def post(self, request):
    
  28.         return HttpResponse("This view only accepts POST")
    
  29. 
    
  30. 
    
  31. class CustomizableView(SimpleView):
    
  32.     parameter = {}
    
  33. 
    
  34. 
    
  35. def decorator(view):
    
  36.     view.is_decorated = True
    
  37.     return view
    
  38. 
    
  39. 
    
  40. class DecoratedDispatchView(SimpleView):
    
  41.     @decorator
    
  42.     def dispatch(self, request, *args, **kwargs):
    
  43.         return super().dispatch(request, *args, **kwargs)
    
  44. 
    
  45. 
    
  46. class AboutTemplateView(TemplateView):
    
  47.     def get(self, request):
    
  48.         return self.render_to_response({})
    
  49. 
    
  50.     def get_template_names(self):
    
  51.         return ["generic_views/about.html"]
    
  52. 
    
  53. 
    
  54. class AboutTemplateAttributeView(TemplateView):
    
  55.     template_name = "generic_views/about.html"
    
  56. 
    
  57.     def get(self, request):
    
  58.         return self.render_to_response(context={})
    
  59. 
    
  60. 
    
  61. class InstanceView(View):
    
  62.     def get(self, request):
    
  63.         return self
    
  64. 
    
  65. 
    
  66. class ViewTest(SimpleTestCase):
    
  67.     rf = RequestFactory()
    
  68. 
    
  69.     def _assert_simple(self, response):
    
  70.         self.assertEqual(response.status_code, 200)
    
  71.         self.assertEqual(response.content, b"This is a simple view")
    
  72. 
    
  73.     def test_no_init_kwargs(self):
    
  74.         """
    
  75.         A view can't be accidentally instantiated before deployment
    
  76.         """
    
  77.         msg = "This method is available only on the class, not on instances."
    
  78.         with self.assertRaisesMessage(AttributeError, msg):
    
  79.             SimpleView(key="value").as_view()
    
  80. 
    
  81.     def test_no_init_args(self):
    
  82.         """
    
  83.         A view can't be accidentally instantiated before deployment
    
  84.         """
    
  85.         msg = "as_view() takes 1 positional argument but 2 were given"
    
  86.         with self.assertRaisesMessage(TypeError, msg):
    
  87.             SimpleView.as_view("value")
    
  88. 
    
  89.     def test_pathological_http_method(self):
    
  90.         """
    
  91.         The edge case of an HTTP request that spoofs an existing method name is
    
  92.         caught.
    
  93.         """
    
  94.         self.assertEqual(
    
  95.             SimpleView.as_view()(
    
  96.                 self.rf.get("/", REQUEST_METHOD="DISPATCH")
    
  97.             ).status_code,
    
  98.             405,
    
  99.         )
    
  100. 
    
  101.     def test_get_only(self):
    
  102.         """
    
  103.         Test a view which only allows GET doesn't allow other methods.
    
  104.         """
    
  105.         self._assert_simple(SimpleView.as_view()(self.rf.get("/")))
    
  106.         self.assertEqual(SimpleView.as_view()(self.rf.post("/")).status_code, 405)
    
  107.         self.assertEqual(
    
  108.             SimpleView.as_view()(self.rf.get("/", REQUEST_METHOD="FAKE")).status_code,
    
  109.             405,
    
  110.         )
    
  111. 
    
  112.     def test_get_and_head(self):
    
  113.         """
    
  114.         Test a view which supplies a GET method also responds correctly to HEAD.
    
  115.         """
    
  116.         self._assert_simple(SimpleView.as_view()(self.rf.get("/")))
    
  117.         response = SimpleView.as_view()(self.rf.head("/"))
    
  118.         self.assertEqual(response.status_code, 200)
    
  119. 
    
  120.     def test_setup_get_and_head(self):
    
  121.         view_instance = SimpleView()
    
  122.         self.assertFalse(hasattr(view_instance, "head"))
    
  123.         view_instance.setup(self.rf.get("/"))
    
  124.         self.assertTrue(hasattr(view_instance, "head"))
    
  125.         self.assertEqual(view_instance.head, view_instance.get)
    
  126. 
    
  127.     def test_head_no_get(self):
    
  128.         """
    
  129.         Test a view which supplies no GET method responds to HEAD with HTTP 405.
    
  130.         """
    
  131.         response = PostOnlyView.as_view()(self.rf.head("/"))
    
  132.         self.assertEqual(response.status_code, 405)
    
  133. 
    
  134.     def test_get_and_post(self):
    
  135.         """
    
  136.         Test a view which only allows both GET and POST.
    
  137.         """
    
  138.         self._assert_simple(SimplePostView.as_view()(self.rf.get("/")))
    
  139.         self._assert_simple(SimplePostView.as_view()(self.rf.post("/")))
    
  140.         self.assertEqual(
    
  141.             SimplePostView.as_view()(
    
  142.                 self.rf.get("/", REQUEST_METHOD="FAKE")
    
  143.             ).status_code,
    
  144.             405,
    
  145.         )
    
  146. 
    
  147.     def test_invalid_keyword_argument(self):
    
  148.         """
    
  149.         View arguments must be predefined on the class and can't
    
  150.         be named like an HTTP method.
    
  151.         """
    
  152.         msg = (
    
  153.             "The method name %s is not accepted as a keyword argument to "
    
  154.             "SimpleView()."
    
  155.         )
    
  156.         # Check each of the allowed method names
    
  157.         for method in SimpleView.http_method_names:
    
  158.             with self.assertRaisesMessage(TypeError, msg % method):
    
  159.                 SimpleView.as_view(**{method: "value"})
    
  160. 
    
  161.         # Check the case view argument is ok if predefined on the class...
    
  162.         CustomizableView.as_view(parameter="value")
    
  163.         # ...but raises errors otherwise.
    
  164.         msg = (
    
  165.             "CustomizableView() received an invalid keyword 'foobar'. "
    
  166.             "as_view only accepts arguments that are already attributes of "
    
  167.             "the class."
    
  168.         )
    
  169.         with self.assertRaisesMessage(TypeError, msg):
    
  170.             CustomizableView.as_view(foobar="value")
    
  171. 
    
  172.     def test_calling_more_than_once(self):
    
  173.         """
    
  174.         Test a view can only be called once.
    
  175.         """
    
  176.         request = self.rf.get("/")
    
  177.         view = InstanceView.as_view()
    
  178.         self.assertNotEqual(view(request), view(request))
    
  179. 
    
  180.     def test_class_attributes(self):
    
  181.         """
    
  182.         The callable returned from as_view() has proper special attributes.
    
  183.         """
    
  184.         cls = SimpleView
    
  185.         view = cls.as_view()
    
  186.         self.assertEqual(view.__doc__, cls.__doc__)
    
  187.         self.assertEqual(view.__name__, "view")
    
  188.         self.assertEqual(view.__module__, cls.__module__)
    
  189.         self.assertEqual(view.__qualname__, f"{cls.as_view.__qualname__}.<locals>.view")
    
  190.         self.assertEqual(view.__annotations__, cls.dispatch.__annotations__)
    
  191.         self.assertFalse(hasattr(view, "__wrapped__"))
    
  192. 
    
  193.     def test_dispatch_decoration(self):
    
  194.         """
    
  195.         Attributes set by decorators on the dispatch method
    
  196.         are also present on the closure.
    
  197.         """
    
  198.         self.assertTrue(DecoratedDispatchView.as_view().is_decorated)
    
  199. 
    
  200.     def test_options(self):
    
  201.         """
    
  202.         Views respond to HTTP OPTIONS requests with an Allow header
    
  203.         appropriate for the methods implemented by the view class.
    
  204.         """
    
  205.         request = self.rf.options("/")
    
  206.         view = SimpleView.as_view()
    
  207.         response = view(request)
    
  208.         self.assertEqual(200, response.status_code)
    
  209.         self.assertTrue(response.headers["Allow"])
    
  210. 
    
  211.     def test_options_for_get_view(self):
    
  212.         """
    
  213.         A view implementing GET allows GET and HEAD.
    
  214.         """
    
  215.         request = self.rf.options("/")
    
  216.         view = SimpleView.as_view()
    
  217.         response = view(request)
    
  218.         self._assert_allows(response, "GET", "HEAD")
    
  219. 
    
  220.     def test_options_for_get_and_post_view(self):
    
  221.         """
    
  222.         A view implementing GET and POST allows GET, HEAD, and POST.
    
  223.         """
    
  224.         request = self.rf.options("/")
    
  225.         view = SimplePostView.as_view()
    
  226.         response = view(request)
    
  227.         self._assert_allows(response, "GET", "HEAD", "POST")
    
  228. 
    
  229.     def test_options_for_post_view(self):
    
  230.         """
    
  231.         A view implementing POST allows POST.
    
  232.         """
    
  233.         request = self.rf.options("/")
    
  234.         view = PostOnlyView.as_view()
    
  235.         response = view(request)
    
  236.         self._assert_allows(response, "POST")
    
  237. 
    
  238.     def _assert_allows(self, response, *expected_methods):
    
  239.         "Assert allowed HTTP methods reported in the Allow response header"
    
  240.         response_allows = set(response.headers["Allow"].split(", "))
    
  241.         self.assertEqual(set(expected_methods + ("OPTIONS",)), response_allows)
    
  242. 
    
  243.     def test_args_kwargs_request_on_self(self):
    
  244.         """
    
  245.         Test a view only has args, kwargs & request once `as_view`
    
  246.         has been called.
    
  247.         """
    
  248.         bare_view = InstanceView()
    
  249.         view = InstanceView.as_view()(self.rf.get("/"))
    
  250.         for attribute in ("args", "kwargs", "request"):
    
  251.             self.assertNotIn(attribute, dir(bare_view))
    
  252.             self.assertIn(attribute, dir(view))
    
  253. 
    
  254.     def test_overridden_setup(self):
    
  255.         class SetAttributeMixin:
    
  256.             def setup(self, request, *args, **kwargs):
    
  257.                 self.attr = True
    
  258.                 super().setup(request, *args, **kwargs)
    
  259. 
    
  260.         class CheckSetupView(SetAttributeMixin, SimpleView):
    
  261.             def dispatch(self, request, *args, **kwargs):
    
  262.                 assert hasattr(self, "attr")
    
  263.                 return super().dispatch(request, *args, **kwargs)
    
  264. 
    
  265.         response = CheckSetupView.as_view()(self.rf.get("/"))
    
  266.         self.assertEqual(response.status_code, 200)
    
  267. 
    
  268.     def test_not_calling_parent_setup_error(self):
    
  269.         class TestView(View):
    
  270.             def setup(self, request, *args, **kwargs):
    
  271.                 pass  # Not calling super().setup()
    
  272. 
    
  273.         msg = (
    
  274.             "TestView instance has no 'request' attribute. Did you override "
    
  275.             "setup() and forget to call super()?"
    
  276.         )
    
  277.         with self.assertRaisesMessage(AttributeError, msg):
    
  278.             TestView.as_view()(self.rf.get("/"))
    
  279. 
    
  280.     def test_setup_adds_args_kwargs_request(self):
    
  281.         request = self.rf.get("/")
    
  282.         args = ("arg 1", "arg 2")
    
  283.         kwargs = {"kwarg_1": 1, "kwarg_2": "year"}
    
  284. 
    
  285.         view = View()
    
  286.         view.setup(request, *args, **kwargs)
    
  287.         self.assertEqual(request, view.request)
    
  288.         self.assertEqual(args, view.args)
    
  289.         self.assertEqual(kwargs, view.kwargs)
    
  290. 
    
  291.     def test_direct_instantiation(self):
    
  292.         """
    
  293.         It should be possible to use the view by directly instantiating it
    
  294.         without going through .as_view() (#21564).
    
  295.         """
    
  296.         view = PostOnlyView()
    
  297.         response = view.dispatch(self.rf.head("/"))
    
  298.         self.assertEqual(response.status_code, 405)
    
  299. 
    
  300. 
    
  301. @override_settings(ROOT_URLCONF="generic_views.urls")
    
  302. class TemplateViewTest(SimpleTestCase):
    
  303.     rf = RequestFactory()
    
  304. 
    
  305.     def _assert_about(self, response):
    
  306.         response.render()
    
  307.         self.assertContains(response, "<h1>About</h1>")
    
  308. 
    
  309.     def test_get(self):
    
  310.         """
    
  311.         Test a view that simply renders a template on GET
    
  312.         """
    
  313.         self._assert_about(AboutTemplateView.as_view()(self.rf.get("/about/")))
    
  314. 
    
  315.     def test_head(self):
    
  316.         """
    
  317.         Test a TemplateView responds correctly to HEAD
    
  318.         """
    
  319.         response = AboutTemplateView.as_view()(self.rf.head("/about/"))
    
  320.         self.assertEqual(response.status_code, 200)
    
  321. 
    
  322.     def test_get_template_attribute(self):
    
  323.         """
    
  324.         Test a view that renders a template on GET with the template name as
    
  325.         an attribute on the class.
    
  326.         """
    
  327.         self._assert_about(AboutTemplateAttributeView.as_view()(self.rf.get("/about/")))
    
  328. 
    
  329.     def test_get_generic_template(self):
    
  330.         """
    
  331.         Test a completely generic view that renders a template on GET
    
  332.         with the template name as an argument at instantiation.
    
  333.         """
    
  334.         self._assert_about(
    
  335.             TemplateView.as_view(template_name="generic_views/about.html")(
    
  336.                 self.rf.get("/about/")
    
  337.             )
    
  338.         )
    
  339. 
    
  340.     def test_template_name_required(self):
    
  341.         """
    
  342.         A template view must provide a template name.
    
  343.         """
    
  344.         msg = (
    
  345.             "TemplateResponseMixin requires either a definition of "
    
  346.             "'template_name' or an implementation of 'get_template_names()'"
    
  347.         )
    
  348.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  349.             self.client.get("/template/no_template/")
    
  350. 
    
  351.     @require_jinja2
    
  352.     def test_template_engine(self):
    
  353.         """
    
  354.         A template view may provide a template engine.
    
  355.         """
    
  356.         request = self.rf.get("/using/")
    
  357.         view = TemplateView.as_view(template_name="generic_views/using.html")
    
  358.         self.assertEqual(view(request).render().content, b"DTL\n")
    
  359.         view = TemplateView.as_view(
    
  360.             template_name="generic_views/using.html", template_engine="django"
    
  361.         )
    
  362.         self.assertEqual(view(request).render().content, b"DTL\n")
    
  363.         view = TemplateView.as_view(
    
  364.             template_name="generic_views/using.html", template_engine="jinja2"
    
  365.         )
    
  366.         self.assertEqual(view(request).render().content, b"Jinja2\n")
    
  367. 
    
  368.     def test_template_params(self):
    
  369.         """
    
  370.         A generic template view passes kwargs as context.
    
  371.         """
    
  372.         response = self.client.get("/template/simple/bar/")
    
  373.         self.assertEqual(response.status_code, 200)
    
  374.         self.assertEqual(response.context["foo"], "bar")
    
  375.         self.assertIsInstance(response.context["view"], View)
    
  376. 
    
  377.     def test_extra_template_params(self):
    
  378.         """
    
  379.         A template view can be customized to return extra context.
    
  380.         """
    
  381.         response = self.client.get("/template/custom/bar/")
    
  382.         self.assertEqual(response.status_code, 200)
    
  383.         self.assertEqual(response.context["foo"], "bar")
    
  384.         self.assertEqual(response.context["key"], "value")
    
  385.         self.assertIsInstance(response.context["view"], View)
    
  386. 
    
  387.     def test_cached_views(self):
    
  388.         """
    
  389.         A template view can be cached
    
  390.         """
    
  391.         response = self.client.get("/template/cached/bar/")
    
  392.         self.assertEqual(response.status_code, 200)
    
  393. 
    
  394.         time.sleep(1.0)
    
  395. 
    
  396.         response2 = self.client.get("/template/cached/bar/")
    
  397.         self.assertEqual(response2.status_code, 200)
    
  398. 
    
  399.         self.assertEqual(response.content, response2.content)
    
  400. 
    
  401.         time.sleep(2.0)
    
  402. 
    
  403.         # Let the cache expire and test again
    
  404.         response2 = self.client.get("/template/cached/bar/")
    
  405.         self.assertEqual(response2.status_code, 200)
    
  406. 
    
  407.         self.assertNotEqual(response.content, response2.content)
    
  408. 
    
  409.     def test_content_type(self):
    
  410.         response = self.client.get("/template/content_type/")
    
  411.         self.assertEqual(response.headers["Content-Type"], "text/plain")
    
  412. 
    
  413.     def test_resolve_view(self):
    
  414.         match = resolve("/template/content_type/")
    
  415.         self.assertIs(match.func.view_class, TemplateView)
    
  416.         self.assertEqual(match.func.view_initkwargs["content_type"], "text/plain")
    
  417. 
    
  418.     def test_resolve_login_required_view(self):
    
  419.         match = resolve("/template/login_required/")
    
  420.         self.assertIs(match.func.view_class, TemplateView)
    
  421. 
    
  422.     def test_extra_context(self):
    
  423.         response = self.client.get("/template/extra_context/")
    
  424.         self.assertEqual(response.context["title"], "Title")
    
  425. 
    
  426. 
    
  427. @override_settings(ROOT_URLCONF="generic_views.urls")
    
  428. class RedirectViewTest(SimpleTestCase):
    
  429.     rf = RequestFactory()
    
  430. 
    
  431.     def test_no_url(self):
    
  432.         "Without any configuration, returns HTTP 410 GONE"
    
  433.         response = RedirectView.as_view()(self.rf.get("/foo/"))
    
  434.         self.assertEqual(response.status_code, 410)
    
  435. 
    
  436.     def test_default_redirect(self):
    
  437.         "Default is a temporary redirect"
    
  438.         response = RedirectView.as_view(url="/bar/")(self.rf.get("/foo/"))
    
  439.         self.assertEqual(response.status_code, 302)
    
  440.         self.assertEqual(response.url, "/bar/")
    
  441. 
    
  442.     def test_permanent_redirect(self):
    
  443.         "Permanent redirects are an option"
    
  444.         response = RedirectView.as_view(url="/bar/", permanent=True)(
    
  445.             self.rf.get("/foo/")
    
  446.         )
    
  447.         self.assertEqual(response.status_code, 301)
    
  448.         self.assertEqual(response.url, "/bar/")
    
  449. 
    
  450.     def test_temporary_redirect(self):
    
  451.         "Temporary redirects are an option"
    
  452.         response = RedirectView.as_view(url="/bar/", permanent=False)(
    
  453.             self.rf.get("/foo/")
    
  454.         )
    
  455.         self.assertEqual(response.status_code, 302)
    
  456.         self.assertEqual(response.url, "/bar/")
    
  457. 
    
  458.     def test_include_args(self):
    
  459.         "GET arguments can be included in the redirected URL"
    
  460.         response = RedirectView.as_view(url="/bar/")(self.rf.get("/foo/"))
    
  461.         self.assertEqual(response.status_code, 302)
    
  462.         self.assertEqual(response.url, "/bar/")
    
  463. 
    
  464.         response = RedirectView.as_view(url="/bar/", query_string=True)(
    
  465.             self.rf.get("/foo/?pork=spam")
    
  466.         )
    
  467.         self.assertEqual(response.status_code, 302)
    
  468.         self.assertEqual(response.url, "/bar/?pork=spam")
    
  469. 
    
  470.     def test_include_urlencoded_args(self):
    
  471.         "GET arguments can be URL-encoded when included in the redirected URL"
    
  472.         response = RedirectView.as_view(url="/bar/", query_string=True)(
    
  473.             self.rf.get("/foo/?unicode=%E2%9C%93")
    
  474.         )
    
  475.         self.assertEqual(response.status_code, 302)
    
  476.         self.assertEqual(response.url, "/bar/?unicode=%E2%9C%93")
    
  477. 
    
  478.     def test_parameter_substitution(self):
    
  479.         "Redirection URLs can be parameterized"
    
  480.         response = RedirectView.as_view(url="/bar/%(object_id)d/")(
    
  481.             self.rf.get("/foo/42/"), object_id=42
    
  482.         )
    
  483.         self.assertEqual(response.status_code, 302)
    
  484.         self.assertEqual(response.url, "/bar/42/")
    
  485. 
    
  486.     def test_named_url_pattern(self):
    
  487.         "Named pattern parameter should reverse to the matching pattern"
    
  488.         response = RedirectView.as_view(pattern_name="artist_detail")(
    
  489.             self.rf.get("/foo/"), pk=1
    
  490.         )
    
  491.         self.assertEqual(response.status_code, 302)
    
  492.         self.assertEqual(response.headers["Location"], "/detail/artist/1/")
    
  493. 
    
  494.     def test_named_url_pattern_using_args(self):
    
  495.         response = RedirectView.as_view(pattern_name="artist_detail")(
    
  496.             self.rf.get("/foo/"), 1
    
  497.         )
    
  498.         self.assertEqual(response.status_code, 302)
    
  499.         self.assertEqual(response.headers["Location"], "/detail/artist/1/")
    
  500. 
    
  501.     def test_redirect_POST(self):
    
  502.         "Default is a temporary redirect"
    
  503.         response = RedirectView.as_view(url="/bar/")(self.rf.post("/foo/"))
    
  504.         self.assertEqual(response.status_code, 302)
    
  505.         self.assertEqual(response.url, "/bar/")
    
  506. 
    
  507.     def test_redirect_HEAD(self):
    
  508.         "Default is a temporary redirect"
    
  509.         response = RedirectView.as_view(url="/bar/")(self.rf.head("/foo/"))
    
  510.         self.assertEqual(response.status_code, 302)
    
  511.         self.assertEqual(response.url, "/bar/")
    
  512. 
    
  513.     def test_redirect_OPTIONS(self):
    
  514.         "Default is a temporary redirect"
    
  515.         response = RedirectView.as_view(url="/bar/")(self.rf.options("/foo/"))
    
  516.         self.assertEqual(response.status_code, 302)
    
  517.         self.assertEqual(response.url, "/bar/")
    
  518. 
    
  519.     def test_redirect_PUT(self):
    
  520.         "Default is a temporary redirect"
    
  521.         response = RedirectView.as_view(url="/bar/")(self.rf.put("/foo/"))
    
  522.         self.assertEqual(response.status_code, 302)
    
  523.         self.assertEqual(response.url, "/bar/")
    
  524. 
    
  525.     def test_redirect_PATCH(self):
    
  526.         "Default is a temporary redirect"
    
  527.         response = RedirectView.as_view(url="/bar/")(self.rf.patch("/foo/"))
    
  528.         self.assertEqual(response.status_code, 302)
    
  529.         self.assertEqual(response.url, "/bar/")
    
  530. 
    
  531.     def test_redirect_DELETE(self):
    
  532.         "Default is a temporary redirect"
    
  533.         response = RedirectView.as_view(url="/bar/")(self.rf.delete("/foo/"))
    
  534.         self.assertEqual(response.status_code, 302)
    
  535.         self.assertEqual(response.url, "/bar/")
    
  536. 
    
  537.     def test_redirect_when_meta_contains_no_query_string(self):
    
  538.         "regression for #16705"
    
  539.         # we can't use self.rf.get because it always sets QUERY_STRING
    
  540.         response = RedirectView.as_view(url="/bar/")(self.rf.request(PATH_INFO="/foo/"))
    
  541.         self.assertEqual(response.status_code, 302)
    
  542. 
    
  543.     def test_direct_instantiation(self):
    
  544.         """
    
  545.         It should be possible to use the view without going through .as_view()
    
  546.         (#21564).
    
  547.         """
    
  548.         view = RedirectView()
    
  549.         response = view.dispatch(self.rf.head("/foo/"))
    
  550.         self.assertEqual(response.status_code, 410)
    
  551. 
    
  552. 
    
  553. class GetContextDataTest(SimpleTestCase):
    
  554.     def test_get_context_data_super(self):
    
  555.         test_view = views.CustomContextView()
    
  556.         context = test_view.get_context_data(kwarg_test="kwarg_value")
    
  557. 
    
  558.         # the test_name key is inserted by the test classes parent
    
  559.         self.assertIn("test_name", context)
    
  560.         self.assertEqual(context["kwarg_test"], "kwarg_value")
    
  561.         self.assertEqual(context["custom_key"], "custom_value")
    
  562. 
    
  563.         # test that kwarg overrides values assigned higher up
    
  564.         context = test_view.get_context_data(test_name="test_value")
    
  565.         self.assertEqual(context["test_name"], "test_value")
    
  566. 
    
  567.     def test_object_at_custom_name_in_context_data(self):
    
  568.         # Checks 'pony' key presence in dict returned by get_context_date
    
  569.         test_view = views.CustomSingleObjectView()
    
  570.         test_view.context_object_name = "pony"
    
  571.         context = test_view.get_context_data()
    
  572.         self.assertEqual(context["pony"], test_view.object)
    
  573. 
    
  574.     def test_object_in_get_context_data(self):
    
  575.         # Checks 'object' key presence in dict returned by get_context_date #20234
    
  576.         test_view = views.CustomSingleObjectView()
    
  577.         context = test_view.get_context_data()
    
  578.         self.assertEqual(context["object"], test_view.object)
    
  579. 
    
  580. 
    
  581. class UseMultipleObjectMixinTest(SimpleTestCase):
    
  582.     rf = RequestFactory()
    
  583. 
    
  584.     def test_use_queryset_from_view(self):
    
  585.         test_view = views.CustomMultipleObjectMixinView()
    
  586.         test_view.get(self.rf.get("/"))
    
  587.         # Don't pass queryset as argument
    
  588.         context = test_view.get_context_data()
    
  589.         self.assertEqual(context["object_list"], test_view.queryset)
    
  590. 
    
  591.     def test_overwrite_queryset(self):
    
  592.         test_view = views.CustomMultipleObjectMixinView()
    
  593.         test_view.get(self.rf.get("/"))
    
  594.         queryset = [{"name": "Lennon"}, {"name": "Ono"}]
    
  595.         self.assertNotEqual(test_view.queryset, queryset)
    
  596.         # Overwrite the view's queryset with queryset from kwarg
    
  597.         context = test_view.get_context_data(object_list=queryset)
    
  598.         self.assertEqual(context["object_list"], queryset)
    
  599. 
    
  600. 
    
  601. class SingleObjectTemplateResponseMixinTest(SimpleTestCase):
    
  602.     def test_template_mixin_without_template(self):
    
  603.         """
    
  604.         We want to makes sure that if you use a template mixin, but forget the
    
  605.         template, it still tells you it's ImproperlyConfigured instead of
    
  606.         TemplateDoesNotExist.
    
  607.         """
    
  608.         view = views.TemplateResponseWithoutTemplate()
    
  609.         msg = (
    
  610.             "TemplateResponseMixin requires either a definition of "
    
  611.             "'template_name' or an implementation of 'get_template_names()'"
    
  612.         )
    
  613.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  614.             view.get_template_names()