Browse Source

Fixed #31877 -- Reverted "Fixed #19878 -- Deprecated TemplateView passing URL kwargs into context."

This reverts commit 4ed534758cb6a11df9f49baddecca5a6cdda9311.
Mariusz Felisiak 4 years ago
parent
commit
bb8f66934d

+ 4 - 26
django/views/generic/base.py

@@ -1,5 +1,4 @@
 import logging
-import warnings
 from functools import update_wrapper
 
 from django.core.exceptions import ImproperlyConfigured
@@ -10,8 +9,6 @@ from django.http import (
 from django.template.response import TemplateResponse
 from django.urls import reverse
 from django.utils.decorators import classonlymethod
-from django.utils.deprecation import RemovedInDjango40Warning
-from django.utils.functional import SimpleLazyObject
 
 logger = logging.getLogger('django.request')
 
@@ -155,33 +152,14 @@ class TemplateResponseMixin:
 
 
 class TemplateView(TemplateResponseMixin, ContextMixin, View):
-    """Render a template."""
+    """
+    Render a template. Pass keyword arguments from the URLconf to the context.
+    """
     def get(self, request, *args, **kwargs):
-        # RemovedInDjango40Warning: when the deprecation ends, replace with:
-        #   context = self.get_context_data()
-        context_kwargs = _wrap_url_kwargs_with_deprecation_warning(kwargs)
-        context = self.get_context_data(**context_kwargs)
+        context = self.get_context_data(**kwargs)
         return self.render_to_response(context)
 
 
-# RemovedInDjango40Warning
-def _wrap_url_kwargs_with_deprecation_warning(url_kwargs):
-    context_kwargs = {}
-    for key, value in url_kwargs.items():
-        # Bind into function closure.
-        @SimpleLazyObject
-        def access_value(key=key, value=value):
-            warnings.warn(
-                'TemplateView passing URL kwargs to the context is '
-                'deprecated. Reference %s in your template through '
-                'view.kwargs instead.' % key,
-                RemovedInDjango40Warning, stacklevel=2,
-            )
-            return value
-        context_kwargs[key] = access_value
-    return context_kwargs
-
-
 class RedirectView(View):
     """Provide a redirect on any GET request."""
     permanent = False

+ 0 - 3
docs/internals/deprecation.txt

@@ -98,9 +98,6 @@ details on these changes.
 
 * The ``list`` message for ``ModelMultipleChoiceField`` will be removed.
 
-* ``django.views.generic.TemplateView`` will no longer pass URL kwargs directly
-  to the ``context``.
-
 * Support for passing raw column aliases to ``QuerySet.order_by()`` will be
   removed.
 

+ 4 - 8
docs/ref/class-based-views/base.txt

@@ -117,7 +117,8 @@ MRO is an acronym for Method Resolution Order.
 
 .. class:: django.views.generic.base.TemplateView
 
-    Renders a given template.
+    Renders a given template, with the context containing parameters captured
+    in the URL.
 
     **Ancestors (MRO)**
 
@@ -161,17 +162,12 @@ MRO is an acronym for Method Resolution Order.
 
     **Context**
 
-    * Populated (through :class:`~django.views.generic.base.ContextMixin`).
+    * Populated (through :class:`~django.views.generic.base.ContextMixin`) with
+      the keyword arguments captured from the URL pattern that served the view.
     * You can also add context using the
       :attr:`~django.views.generic.base.ContextMixin.extra_context` keyword
       argument for :meth:`~django.views.generic.base.View.as_view`.
 
-    .. deprecated:: 3.1
-
-        Starting in Django 4.0, the keyword arguments captured from the URL
-        pattern won't be passed to the context. Reference them with
-        ``view.kwargs`` instead.
-
 ``RedirectView``
 ================
 

+ 4 - 0
docs/releases/3.1.1.txt

@@ -31,3 +31,7 @@ Bugfixes
 
 * Fixed a regression in Django 3.1 that caused a crash when decoding an invalid
   session data (:ticket:`31895`).
+
+* Reverted a deprecation in Django 3.1 that caused a crash when passing
+  deprecated keyword arguments to a queryset in
+  ``TemplateView.get_context_data()`` (:ticket:`31877`).

+ 0 - 4
docs/releases/3.1.txt

@@ -798,10 +798,6 @@ Miscellaneous
 * The ``list`` message for :class:`~django.forms.ModelMultipleChoiceField` is
   deprecated in favor of ``invalid_list``.
 
-* The passing of URL kwargs directly to the context by
-  :class:`~django.views.generic.base.TemplateView` is deprecated. Reference
-  them in the template with ``view.kwargs`` instead.
-
 * Passing raw column aliases to :meth:`.QuerySet.order_by` is deprecated. The
   same result can be achieved by passing aliases in a
   :class:`~django.db.models.expressions.RawSQL` instead beforehand.

+ 20 - 39
tests/generic_views/test_base.py

@@ -2,12 +2,9 @@ import time
 
 from django.core.exceptions import ImproperlyConfigured
 from django.http import HttpResponse
-from django.test import (
-    RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
-)
+from django.test import RequestFactory, SimpleTestCase, override_settings
 from django.test.utils import require_jinja2
 from django.urls import resolve
-from django.utils.deprecation import RemovedInDjango40Warning
 from django.views.generic import RedirectView, TemplateView, View
 
 from . import views
@@ -350,6 +347,25 @@ class TemplateViewTest(SimpleTestCase):
         view = TemplateView.as_view(template_name='generic_views/using.html', template_engine='jinja2')
         self.assertEqual(view(request).render().content, b'Jinja2\n')
 
+    def test_template_params(self):
+        """
+        A generic template view passes kwargs as context.
+        """
+        response = self.client.get('/template/simple/bar/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.context['foo'], 'bar')
+        self.assertIsInstance(response.context['view'], View)
+
+    def test_extra_template_params(self):
+        """
+        A template view can be customized to return extra context.
+        """
+        response = self.client.get('/template/custom/bar/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.context['foo'], 'bar')
+        self.assertEqual(response.context['key'], 'value')
+        self.assertIsInstance(response.context['view'], View)
+
     def test_cached_views(self):
         """
         A template view can be cached
@@ -568,38 +584,3 @@ class SingleObjectTemplateResponseMixinTest(SimpleTestCase):
         )
         with self.assertRaisesMessage(ImproperlyConfigured, msg):
             view.get_template_names()
-
-
-@override_settings(ROOT_URLCONF='generic_views.urls')
-class DeprecationTests(SimpleTestCase):
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_template_params(self):
-        """A generic template view passes kwargs as context."""
-        response = self.client.get('/template/simple/bar/')
-        self.assertEqual(response.status_code, 200)
-        self.assertEqual(response.context['foo'], 'bar')
-        self.assertIsInstance(response.context['view'], View)
-
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_extra_template_params(self):
-        """A template view can be customized to return extra context."""
-        response = self.client.get('/template/custom/bar1/bar2/')
-        self.assertEqual(response.status_code, 200)
-        self.assertEqual(response.context['foo1'], 'bar1')
-        self.assertEqual(response.context['foo2'], 'bar2')
-        self.assertEqual(response.context['key'], 'value')
-        self.assertIsInstance(response.context['view'], View)
-
-    def test_template_params_warning(self):
-        response = self.client.get('/template/custom/bar1/bar2/')
-        self.assertEqual(response.status_code, 200)
-        msg = (
-            'TemplateView passing URL kwargs to the context is deprecated. '
-            'Reference %s in your template through view.kwargs instead.'
-        )
-        with self.assertRaisesMessage(RemovedInDjango40Warning, msg % 'foo1'):
-            str(response.context['foo1'])
-        with self.assertRaisesMessage(RemovedInDjango40Warning, msg % 'foo2'):
-            str(response.context['foo2'])
-        self.assertEqual(response.context['key'], 'value')
-        self.assertIsInstance(response.context['view'], View)

+ 1 - 4
tests/generic_views/urls.py

@@ -12,10 +12,7 @@ urlpatterns = [
     path('template/no_template/', TemplateView.as_view()),
     path('template/login_required/', login_required(TemplateView.as_view())),
     path('template/simple/<foo>/', TemplateView.as_view(template_name='generic_views/about.html')),
-    path(
-        'template/custom/<foo1>/<foo2>/',
-        views.CustomTemplateView.as_view(template_name='generic_views/about.html'),
-    ),
+    path('template/custom/<foo>/', views.CustomTemplateView.as_view(template_name='generic_views/about.html')),
     path(
         'template/content_type/',
         TemplateView.as_view(template_name='generic_views/robots.txt', content_type='text/plain'),