From 4696cd9671243958fd4a596631d75b3cbca325c3 Mon Sep 17 00:00:00 2001 From: mlavin Date: Sun, 20 Apr 2014 08:58:29 -0400 Subject: [PATCH] Fixed #22477 -- Removed contrib middleware from the global settings defaults. Also added a compatibility check for changed middleware defaults. Forwardport of d94de802d3 from stable/1.7.x --- django/conf/global_settings.py | 5 --- .../auth/tests/test_context_processors.py | 19 +++++++--- django/core/checks/__init__.py | 1 + .../core/checks/compatibility/django_1_7_0.py | 36 +++++++++++++++++++ docs/ref/settings.txt | 12 ++++--- docs/releases/1.7.txt | 23 ++++++++++++ tests/admin_scripts/tests.py | 3 +- tests/check_framework/tests.py | 35 ++++++++++++++++++ tests/runtests.py | 12 +++++++ 9 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 django/core/checks/compatibility/django_1_7_0.py diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 6d15063bdc..45c689d7dd 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -454,12 +454,7 @@ SECURE_PROXY_SSL_HEADER = None # response phase the middleware will be applied in reverse order. MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - # 'django.middleware.http.ConditionalGetMiddleware', - # 'django.middleware.gzip.GZipMiddleware', ) ############ diff --git a/django/contrib/auth/tests/test_context_processors.py b/django/contrib/auth/tests/test_context_processors.py index 2e4cd00802..9de08bf96a 100644 --- a/django/contrib/auth/tests/test_context_processors.py +++ b/django/contrib/auth/tests/test_context_processors.py @@ -1,6 +1,5 @@ import os -from django.conf import global_settings from django.contrib.auth import authenticate from django.contrib.auth.tests.utils import skipIfCustomUser from django.contrib.auth.models import User, Permission @@ -77,8 +76,13 @@ class AuthContextProcessorTests(TestCase): fixtures = ['context-processors-users.xml'] @override_settings( - MIDDLEWARE_CLASSES=global_settings.MIDDLEWARE_CLASSES, - TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS, + MIDDLEWARE_CLASSES=( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + ), + TEMPLATE_CONTEXT_PROCESSORS=( + 'django.contrib.auth.context_processors.auth', + ), ) def test_session_not_accessed(self): """ @@ -89,8 +93,13 @@ class AuthContextProcessorTests(TestCase): self.assertContains(response, "Session not accessed") @override_settings( - MIDDLEWARE_CLASSES=global_settings.MIDDLEWARE_CLASSES, - TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS, + MIDDLEWARE_CLASSES=( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + ), + TEMPLATE_CONTEXT_PROCESSORS=( + 'django.contrib.auth.context_processors.auth', + ), ) def test_session_is_accessed(self): """ diff --git a/django/core/checks/__init__.py b/django/core/checks/__init__.py index 0d2780abd3..d215b82513 100644 --- a/django/core/checks/__init__.py +++ b/django/core/checks/__init__.py @@ -8,6 +8,7 @@ from .registry import register, run_checks, tag_exists, Tags # Import these to force registration of checks import django.core.checks.compatibility.django_1_6_0 # NOQA +import django.core.checks.compatibility.django_1_7_0 # NOQA import django.core.checks.model_checks # NOQA __all__ = [ diff --git a/django/core/checks/compatibility/django_1_7_0.py b/django/core/checks/compatibility/django_1_7_0.py new file mode 100644 index 0000000000..7340be6915 --- /dev/null +++ b/django/core/checks/compatibility/django_1_7_0.py @@ -0,0 +1,36 @@ +from __future__ import unicode_literals + +from .. import Warning, register, Tags + + +@register(Tags.compatibility) +def check_1_7_compatibility(**kwargs): + errors = [] + errors.extend(_check_middleware_classes(**kwargs)) + return errors + + +def _check_middleware_classes(app_configs=None, **kwargs): + """ + Checks if the user has *not* overridden the ``MIDDLEWARE_CLASSES`` setting & + warns them about the global default changes. + """ + from django.conf import settings + + # MIDDLEWARE_CLASSES is overridden by default by startproject. If users + # have removed this override then we'll warn them about the default changes. + if not settings.is_overridden('MIDDLEWARE_CLASSES'): + return [ + Warning( + "MIDDLEWARE_CLASSES is not set.", + hint=("Django 1.7 changed the global defaults for the MIDDLEWARE_CLASSES." + "django.contrib.sessions.middleware.SessionMiddleware, " + "django.contrib.auth.middleware.AuthenticationMiddleware, and " + "django.contrib.messages.middleware.MessageMiddleware were removed from the defaults." + "If your project needs these middleware then you should configure this setting."), + obj=None, + id='1_7.W001', + ) + ] + else: + return [] diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 58cb7061b5..d9697a5bcb 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1734,13 +1734,17 @@ MIDDLEWARE_CLASSES Default:: ('django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware',) + 'django.middleware.csrf.CsrfViewMiddleware',) A tuple of middleware classes to use. See :doc:`/topics/http/middleware`. +.. versionchanged:: 1.7 + + :class:`~django.contrib.sessions.middleware.SessionMiddleware`, + :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`, and + :class:`~django.contrib.messages.middleware.MessageMiddleware` were removed + from this setting. + .. setting:: MIGRATION_MODULES MIGRATION_MODULES diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index c40940fc42..560f0562e9 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -68,6 +68,8 @@ but a few of the key features are: inside ``TransactionTestCase`` :ref:`unless specifically requested `. +.. _app-loading-refactor-17-release-note: + App-loading refactor ~~~~~~~~~~~~~~~~~~~~ @@ -1114,6 +1116,27 @@ in a test class which is a subclass of :class:`~django.test.TransactionTestCase` rather than :class:`~django.test.TestCase`. +Contrib middleware removed from default :setting:`MIDDLEWARE_CLASSES` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :ref:`app-loading refactor ` +deprecated using models from apps which are not part of the +:setting:`INSTALLED_APPS` setting. This exposed an incompatibility between +the default :setting:`INSTALLED_APPS` and :setting:`MIDDLEWARE_CLASSES` in the +global defaults (``django.conf.global_settings``). To bring these settings in +sync and prevent deprecation warnings when doing things like testing reusable +apps with minimal settings, +:class:`~django.contrib.sessions.middleware.SessionMiddleware`, +:class:`~django.contrib.auth.middleware.AuthenticationMiddleware`, and +:class:`~django.contrib.messages.middleware.MessageMiddleware` were removed +from the defaults. These classes will still be included in the default settings +generated by :djadmin:`startproject`. Most projects will not be affected by +this change but if you were not previously declaring the +:setting:`MIDDLEWARE_CLASSES` in your project settings and relying on the +global default you should ensure that the new defaults are in line with your +project's needs. You should also check for any code that accesses +``django.conf.global_settings.MIDDLEWARE_CLASSES`` directly. + Miscellaneous ~~~~~~~~~~~~~ diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 4f41e876bc..5c28732319 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -58,11 +58,12 @@ class AdminScriptTestCase(unittest.TestCase): 'ROOT_URLCONF', 'SECRET_KEY', 'TEST_RUNNER', # We need to include TEST_RUNNER, otherwise we get a compatibility warning. + 'MIDDLEWARE_CLASSES', # We need to include MIDDLEWARE_CLASSES, otherwise we get a compatibility warning. ] for s in exports: if hasattr(settings, s): o = getattr(settings, s) - if not isinstance(o, dict): + if not isinstance(o, (dict, tuple, list)): o = "'%s'" % o settings_file.write("%s = %s\n" % (s, o)) diff --git a/tests/check_framework/tests.py b/tests/check_framework/tests.py index 4c861ed509..5325e718bf 100644 --- a/tests/check_framework/tests.py +++ b/tests/check_framework/tests.py @@ -10,6 +10,7 @@ from django.core import checks from django.core.checks import Error, Warning from django.core.checks.registry import CheckRegistry from django.core.checks.compatibility.django_1_6_0 import check_1_6_compatibility +from django.core.checks.compatibility.django_1_7_0 import check_1_7_compatibility from django.core.management.base import CommandError from django.core.management import call_command from django.db.models.fields import NOT_PROVIDED @@ -148,6 +149,40 @@ class Django_1_6_0_CompatibilityChecks(TestCase): boolean_field.default = old_default +class Django_1_7_0_CompatibilityChecks(TestCase): + + @override_settings(MIDDLEWARE_CLASSES=('django.contrib.sessions.middleware.SessionMiddleware',)) + def test_middleware_classes_overridden(self): + errors = check_1_7_compatibility() + self.assertEqual(errors, []) + + def test_middleware_classes_not_set_explicitly(self): + # If MIDDLEWARE_CLASSES was set explicitly, temporarily pretend it wasn't + middleware_classes_overridden = False + if 'MIDDLEWARE_CLASSES' in settings._wrapped._explicit_settings: + middleware_classes_overridden = True + settings._wrapped._explicit_settings.remove('MIDDLEWARE_CLASSES') + try: + errors = check_1_7_compatibility() + expected = [ + checks.Warning( + "MIDDLEWARE_CLASSES is not set.", + hint=("Django 1.7 changed the global defaults for the MIDDLEWARE_CLASSES." + "django.contrib.sessions.middleware.SessionMiddleware, " + "django.contrib.auth.middleware.AuthenticationMiddleware, and " + "django.contrib.messages.middleware.MessageMiddleware were removed from the defaults." + "If your project needs these middleware then you should configure this setting."), + obj=None, + id='1_7.W001', + ) + ] + self.assertEqual(errors, expected) + finally: + # Restore settings value + if middleware_classes_overridden: + settings._wrapped._explicit_settings.add('MIDDLEWARE_CLASSES') + + def simple_system_check(**kwargs): simple_system_check.kwargs = kwargs return [] diff --git a/tests/runtests.py b/tests/runtests.py index e828faeea8..c084f2590b 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -58,6 +58,14 @@ ALWAYS_INSTALLED_APPS = [ 'servers.another_app', ] +ALWAYS_MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + def get_test_modules(): from django.contrib.gis.tests.utils import HAS_SPATIAL_DB @@ -106,6 +114,7 @@ def setup(verbosity, test_labels): 'LANGUAGE_CODE': settings.LANGUAGE_CODE, 'STATIC_URL': settings.STATIC_URL, 'STATIC_ROOT': settings.STATIC_ROOT, + 'MIDDLEWARE_CLASSES': settings.MIDDLEWARE_CLASSES, } # Redirect some settings for the duration of these tests. @@ -116,6 +125,9 @@ def setup(verbosity, test_labels): settings.TEMPLATE_DIRS = (os.path.join(RUNTESTS_DIR, TEST_TEMPLATE_DIR),) settings.LANGUAGE_CODE = 'en' settings.SITE_ID = 1 + settings.MIDDLEWARE_CLASSES = ALWAYS_MIDDLEWARE_CLASSES + # Ensure the middleware classes are seen as overridden otherwise we get a compatibility warning. + settings._explicit_settings.add('MIDDLEWARE_CLASSES') if verbosity > 0: # Ensure any warnings captured to logging are piped through a verbose