فهرست منبع

Refs #26447 -- Removed the USE_ETAGS setting per deprecation timeline.

Tim Graham 7 سال پیش
والد
کامیت
48d57788ee

+ 0 - 5
django/conf/global_settings.py

@@ -21,11 +21,6 @@ DEBUG = False
 # on a live site.
 DEBUG_PROPAGATE_EXCEPTIONS = False
 
-# Whether to use the "ETag" header. This saves bandwidth but slows down performance.
-# Deprecated (RemovedInDjango21Warning) in favor of ConditionalGetMiddleware
-# which sets the ETag regardless of this setting.
-USE_ETAGS = False
-
 # People who get code error notifications.
 # In the format [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')]
 ADMINS = []

+ 1 - 32
django/middleware/common.py

@@ -1,5 +1,4 @@
 import re
-import warnings
 from urllib.parse import urlparse
 
 from django.conf import settings
@@ -7,10 +6,7 @@ from django.core.exceptions import PermissionDenied
 from django.core.mail import mail_managers
 from django.http import HttpResponsePermanentRedirect
 from django.urls import is_valid_path
-from django.utils.cache import (
-    cc_delim_re, get_conditional_response, set_response_etag,
-)
-from django.utils.deprecation import MiddlewareMixin, RemovedInDjango21Warning
+from django.utils.deprecation import MiddlewareMixin
 
 
 class CommonMiddleware(MiddlewareMixin):
@@ -30,11 +26,6 @@ class CommonMiddleware(MiddlewareMixin):
 
           This behavior can be customized by subclassing CommonMiddleware and
           overriding the response_redirect_class attribute.
-
-        - ETags: If the USE_ETAGS setting is set, ETags will be calculated from
-          the entire page content and Not Modified responses will be returned
-          appropriately. USE_ETAGS is deprecated in favor of
-          ConditionalGetMiddleware.
     """
 
     response_redirect_class = HttpResponsePermanentRedirect
@@ -114,23 +105,6 @@ class CommonMiddleware(MiddlewareMixin):
             if self.should_redirect_with_slash(request):
                 return self.response_redirect_class(self.get_full_path_with_slash(request))
 
-        if settings.USE_ETAGS and self.needs_etag(response):
-            warnings.warn(
-                "The USE_ETAGS setting is deprecated in favor of "
-                "ConditionalGetMiddleware which sets the ETag regardless of "
-                "the setting. CommonMiddleware won't do ETag processing in "
-                "Django 2.1.",
-                RemovedInDjango21Warning
-            )
-            if not response.has_header('ETag'):
-                set_response_etag(response)
-
-            if response.has_header('ETag'):
-                return get_conditional_response(
-                    request,
-                    etag=response['ETag'],
-                    response=response,
-                )
         # Add the Content-Length header to non-streaming responses if not
         # already set.
         if not response.streaming and not response.has_header('Content-Length'):
@@ -138,11 +112,6 @@ class CommonMiddleware(MiddlewareMixin):
 
         return response
 
-    def needs_etag(self, response):
-        """Return True if an ETag header should be added to response."""
-        cache_control_headers = cc_delim_re.split(response.get('Cache-Control', ''))
-        return all(header.lower() != 'no-store' for header in cache_control_headers)
-
 
 class BrokenLinkEmailsMiddleware(MiddlewareMixin):
 

+ 0 - 14
django/utils/cache.py

@@ -20,12 +20,10 @@ import hashlib
 import logging
 import re
 import time
-import warnings
 
 from django.conf import settings
 from django.core.cache import caches
 from django.http import HttpResponse, HttpResponseNotModified
-from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.encoding import force_bytes, force_text, iri_to_uri
 from django.utils.http import (
     http_date, parse_etags, parse_http_date_safe, quote_etag,
@@ -248,18 +246,6 @@ def patch_response_headers(response, cache_timeout=None):
         cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
     if cache_timeout < 0:
         cache_timeout = 0  # Can't have max-age negative
-    if settings.USE_ETAGS and not response.has_header('ETag'):
-        warnings.warn(
-            "The USE_ETAGS setting is deprecated in favor of "
-            "ConditionalGetMiddleware which sets the ETag regardless of the "
-            "setting. patch_response_headers() won't do ETag processing in "
-            "Django 2.1.",
-            RemovedInDjango21Warning
-        )
-        if hasattr(response, 'render') and callable(response.render):
-            response.add_post_render_callback(set_response_etag)
-        else:
-            response = set_response_etag(response)
     if not response.has_header('Expires'):
         response['Expires'] = http_date(time.time() + cache_timeout)
     patch_cache_control(response, max_age=cache_timeout)

+ 0 - 16
docs/ref/middleware.txt

@@ -61,23 +61,12 @@ Adds a few conveniences for perfectionists:
   indexer would treat them as separate URLs -- so it's best practice to
   normalize URLs.
 
-* Handles ETags based on the :setting:`USE_ETAGS` setting. If
-  :setting:`USE_ETAGS` is set to ``True``, Django will calculate an ETag
-  for each request by MD5-hashing the page content, and it'll take care of
-  sending ``Not Modified`` responses, if appropriate.
-
 * Sets the ``Content-Length`` header for non-streaming responses.
 
 .. versionchanged:: 1.11
 
     Older versions didn't set the ``Content-Length`` header.
 
-.. deprecated:: 1.11
-
-    The :setting:`USE_ETAGS` setting is deprecated in favor of using
-    :class:`~django.middleware.http.ConditionalGetMiddleware` for ETag
-    processing.
-
 .. attribute:: CommonMiddleware.response_redirect_class
 
 Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
@@ -472,11 +461,6 @@ Here are some hints about the ordering of various Django middleware classes:
 
    After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
 
-#. :class:`~django.middleware.http.ConditionalGetMiddleware`
-
-   Before ``CommonMiddleware``: uses its ``ETag`` header when
-   :setting:`USE_ETAGS` = ``True``.
-
 #. :class:`~django.contrib.sessions.middleware.SessionMiddleware`
 
    After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.

+ 0 - 18
docs/ref/settings.txt

@@ -2593,23 +2593,6 @@ the correct environment.
 
 .. _list of time zones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
 
-.. setting:: USE_ETAGS
-
-``USE_ETAGS``
--------------
-
-Default: ``False``
-
-A boolean that specifies whether to output the ``ETag`` header. This saves
-bandwidth but slows down performance. This is used by the
-:class:`~django.middleware.common.CommonMiddleware` and in the :doc:`cache
-framework </topics/cache>`.
-
-.. deprecated:: 1.11
-
-    This setting is deprecated in favor of using ``ConditionalGetMiddleware``,
-    which sets an ETag regardless of this setting.
-
 .. setting:: USE_I18N
 
 ``USE_I18N``
@@ -3438,7 +3421,6 @@ HTTP
   * :setting:`SECURE_SSL_HOST`
   * :setting:`SECURE_SSL_REDIRECT`
 * :setting:`SIGNING_BACKEND`
-* :setting:`USE_ETAGS`
 * :setting:`USE_X_FORWARDED_HOST`
 * :setting:`USE_X_FORWARDED_PORT`
 * :setting:`WSGI_APPLICATION`

+ 0 - 6
docs/ref/utils.txt

@@ -52,7 +52,6 @@ need to distinguish caches by the ``Accept-language`` header.
 
     Adds some useful headers to the given ``HttpResponse`` object:
 
-    * ``ETag``
     * ``Expires``
     * ``Cache-Control``
 
@@ -65,11 +64,6 @@ need to distinguish caches by the ``Accept-language`` header.
 
         In older versions, the ``Last-Modified`` header was also set.
 
-    .. deprecated:: 1.11
-
-        Since the ``USE_ETAGS`` setting is deprecated, this function won't set
-        the ``ETag`` header when the deprecation ends in Django 2.1.
-
 .. function:: add_never_cache_headers(response)
 
     Adds a ``Cache-Control: max-age=0, no-cache, no-store, must-revalidate``

+ 3 - 0
docs/releases/2.1.txt

@@ -251,3 +251,6 @@ how to remove usage of these features.
   as the first positional argument.
 
 * The ``django.db.models.permalink()`` decorator is removed.
+
+* The ``USE_ETAGS`` setting is removed. ``CommonMiddleware`` and
+  ``django.utils.cache.patch_response_headers()`` no longer set ETags.

+ 1 - 19
tests/admin_views/tests.py

@@ -25,14 +25,12 @@ from django.core.files import temp as tempfile
 from django.forms.utils import ErrorList
 from django.template.response import TemplateResponse
 from django.test import (
-    SimpleTestCase, TestCase, ignore_warnings, modify_settings,
-    override_settings, skipUnlessDBFeature,
+    TestCase, modify_settings, override_settings, skipUnlessDBFeature,
 )
 from django.test.utils import override_script_prefix, patch_logger
 from django.urls import NoReverseMatch, resolve, reverse
 from django.utils import formats, translation
 from django.utils.cache import get_max_age
-from django.utils.deprecation import RemovedInDjango21Warning
 from django.utils.encoding import force_bytes, force_text, iri_to_uri
 from django.utils.html import escape
 from django.utils.http import urlencode
@@ -5809,22 +5807,6 @@ class InlineAdminViewOnSiteTest(TestCase):
         self.assertContains(response, '"/worker_inline/%s/%s/"' % (self.w1.surname, self.w1.name))
 
 
-@override_settings(ROOT_URLCONF='admin_views.urls')
-class TestETagWithAdminView(SimpleTestCase):
-    # The admin is compatible with ETags (#16003).
-
-    def test_admin(self):
-        with self.settings(USE_ETAGS=False):
-            response = self.client.get(reverse('admin:index'))
-            self.assertEqual(response.status_code, 302)
-            self.assertFalse(response.has_header('ETag'))
-
-        with self.settings(USE_ETAGS=True), ignore_warnings(category=RemovedInDjango21Warning):
-            response = self.client.get(reverse('admin:index'))
-            self.assertEqual(response.status_code, 302)
-            self.assertTrue(response.has_header('ETag'))
-
-
 @override_settings(ROOT_URLCONF='admin_views.urls')
 class GetFormsetsWithInlinesArgumentTest(TestCase):
     """

+ 2 - 36
tests/cache/tests.py

@@ -32,15 +32,13 @@ from django.template.context_processors import csrf
 from django.template.response import TemplateResponse
 from django.test import (
     RequestFactory, SimpleTestCase, TestCase, TransactionTestCase,
-    ignore_warnings, override_settings,
+    override_settings,
 )
 from django.test.signals import setting_changed
 from django.utils import timezone, translation
 from django.utils.cache import (
-    get_cache_key, learn_cache_key, patch_cache_control,
-    patch_response_headers, patch_vary_headers,
+    get_cache_key, learn_cache_key, patch_cache_control, patch_vary_headers,
 )
-from django.utils.deprecation import RemovedInDjango21Warning
 from django.views.decorators.cache import cache_page
 
 from .models import Poll, expensive_calculation
@@ -1838,11 +1836,9 @@ class CacheI18nTest(TestCase):
                 "Cache keys should include the time zone name when time zones are active"
             )
 
-    @ignore_warnings(category=RemovedInDjango21Warning)  # USE_ETAGS=True
     @override_settings(
         CACHE_MIDDLEWARE_KEY_PREFIX="test",
         CACHE_MIDDLEWARE_SECONDS=60,
-        USE_ETAGS=True,
         USE_I18N=True,
     )
     def test_middleware(self):
@@ -1884,14 +1880,6 @@ class CacheI18nTest(TestCase):
         # The cache can be recovered
         self.assertIsNotNone(get_cache_data)
         self.assertEqual(get_cache_data.content, en_message.encode())
-        # ETags are used.
-        self.assertTrue(get_cache_data.has_header('ETag'))
-        # ETags can be disabled.
-        with self.settings(USE_ETAGS=False):
-            request._cache_update_cache = True
-            set_cache(request, 'en', en_message)
-            get_cache_data = FetchFromCacheMiddleware().process_request(request)
-            self.assertFalse(get_cache_data.has_header('ETag'))
         # change the session language and set content
         request = self.factory.get(self.path)
         request._cache_update_cache = True
@@ -1911,7 +1899,6 @@ class CacheI18nTest(TestCase):
     @override_settings(
         CACHE_MIDDLEWARE_KEY_PREFIX="test",
         CACHE_MIDDLEWARE_SECONDS=60,
-        USE_ETAGS=True,
     )
     def test_middleware_doesnt_cache_streaming_response(self):
         request = self.factory.get(self.path)
@@ -2232,27 +2219,6 @@ class TestWithTemplateResponse(SimpleTestCase):
             '0f1c2d56633c943073c4569d9a9502fe.d41d8cd98f00b204e9800998ecf8427e'
         )
 
-    @override_settings(USE_ETAGS=False)
-    def test_without_etag(self):
-        template = engines['django'].from_string("This is a test")
-        response = TemplateResponse(HttpRequest(), template)
-        self.assertFalse(response.has_header('ETag'))
-        patch_response_headers(response)
-        self.assertFalse(response.has_header('ETag'))
-        response = response.render()
-        self.assertFalse(response.has_header('ETag'))
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_with_etag(self):
-        template = engines['django'].from_string("This is a test")
-        response = TemplateResponse(HttpRequest(), template)
-        self.assertFalse(response.has_header('ETag'))
-        patch_response_headers(response)
-        self.assertFalse(response.has_header('ETag'))
-        response = response.render()
-        self.assertTrue(response.has_header('ETag'))
-
 
 class TestMakeTemplateFragmentKey(SimpleTestCase):
     def test_without_vary_on(self):

+ 1 - 57
tests/middleware/tests.py

@@ -18,10 +18,7 @@ from django.middleware.common import (
 )
 from django.middleware.gzip import GZipMiddleware
 from django.middleware.http import ConditionalGetMiddleware
-from django.test import (
-    RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
-)
-from django.utils.deprecation import RemovedInDjango21Warning
+from django.test import RequestFactory, SimpleTestCase, override_settings
 
 int2byte = struct.Struct(">B").pack
 
@@ -265,57 +262,6 @@ class CommonMiddlewareTest(SimpleTestCase):
         self.assertEqual(r.status_code, 301)
         self.assertEqual(r.url, 'http://www.testserver/customurlconf/slash/')
 
-    # ETag + If-Not-Modified support tests
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_etag(self):
-        req = HttpRequest()
-        res = HttpResponse('content')
-        self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_etag_streaming_response(self):
-        req = HttpRequest()
-        res = StreamingHttpResponse(['content'])
-        res['ETag'] = 'tomatoes'
-        self.assertEqual(CommonMiddleware().process_response(req, res).get('ETag'), 'tomatoes')
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_no_etag_streaming_response(self):
-        req = HttpRequest()
-        res = StreamingHttpResponse(['content'])
-        self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_no_etag_no_store_cache(self):
-        req = HttpRequest()
-        res = HttpResponse('content')
-        res['Cache-Control'] = 'No-Cache, No-Store, Max-age=0'
-        self.assertFalse(CommonMiddleware().process_response(req, res).has_header('ETag'))
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_etag_extended_cache_control(self):
-        req = HttpRequest()
-        res = HttpResponse('content')
-        res['Cache-Control'] = 'my-directive="my-no-store"'
-        self.assertTrue(CommonMiddleware().process_response(req, res).has_header('ETag'))
-
-    @ignore_warnings(category=RemovedInDjango21Warning)
-    @override_settings(USE_ETAGS=True)
-    def test_if_none_match(self):
-        first_req = HttpRequest()
-        first_res = CommonMiddleware().process_response(first_req, HttpResponse('content'))
-        second_req = HttpRequest()
-        second_req.method = 'GET'
-        second_req.META['HTTP_IF_NONE_MATCH'] = first_res['ETag']
-        second_res = CommonMiddleware().process_response(second_req, HttpResponse('content'))
-        self.assertEqual(second_res.status_code, 304)
-
     # Tests for the Content-Length header
 
     def test_content_length_header_added(self):
@@ -855,8 +801,6 @@ class GZipMiddlewareTest(SimpleTestCase):
         self.assertEqual(self.get_mtime(r2.content), 0)
 
 
-@ignore_warnings(category=RemovedInDjango21Warning)
-@override_settings(USE_ETAGS=True)
 class ETagGZipMiddlewareTest(SimpleTestCase):
     """
     ETags are handled properly by GZipMiddleware.