diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 2f2cec6f84..1d90d6fc0a 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -9,9 +9,11 @@ a list of all possible variables. import importlib import os import time +import warnings from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured +from django.utils.deprecation import RemovedInDjango30Warning from django.utils.functional import LazyObject, empty ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" @@ -128,6 +130,9 @@ class Settings: if not self.SECRET_KEY: raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") + if self.is_overridden('DEFAULT_CONTENT_TYPE'): + warnings.warn('The DEFAULT_CONTENT_TYPE setting is deprecated.', RemovedInDjango30Warning) + if hasattr(time, 'tzset') and self.TIME_ZONE: # When we can, attempt to validate the timezone. If we can't find # this file, no check happens and it's harmless. @@ -173,6 +178,8 @@ class UserSettingsHolder: def __setattr__(self, name, value): self._deleted.discard(name) + if name == 'DEFAULT_CONTENT_TYPE': + warnings.warn('The DEFAULT_CONTENT_TYPE setting is deprecated.', RemovedInDjango30Warning) super().__setattr__(name, value) def __delattr__(self, name): diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 56aa7adacf..4f025f8d1f 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -19,6 +19,8 @@ details on these changes. * ``django.shortcuts.render_to_response()`` will be removed. +* The ``DEFAULT_CONTENT_TYPE`` setting will be removed. + .. _deprecation-removed-in-2.1: 2.1 diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 2dd7e57588..02f84d90c6 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1140,6 +1140,11 @@ Default content type to use for all ``HttpResponse`` objects, if a MIME type isn't manually specified. Used with :setting:`DEFAULT_CHARSET` to construct the ``Content-Type`` header. +.. deprecated:: 2.0 + + This setting is deprecated because it doesn't interact well with + third-party apps and is obsolete since HTML5 has mostly superseded XHTML. + .. setting:: DEFAULT_EXCEPTION_REPORTER_FILTER ``DEFAULT_EXCEPTION_REPORTER_FILTER`` diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index c4f65ec9ac..82cc840ddc 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -301,6 +301,10 @@ Miscellaneous :func:`django.shortcuts.render`. ``render()`` takes the same arguments except that is also requires a ``request``. +* The ``DEFAULT_CONTENT_TYPE`` setting is deprecated. It doesn't interact well + well with third-party apps and is obsolete since HTML5 has mostly superseded + XHTML. + .. _removed-features-2.0: Features removed in 2.0 diff --git a/tests/view_tests/tests/test_default_content_type.py b/tests/view_tests/tests/test_default_content_type.py new file mode 100644 index 0000000000..db5f364f26 --- /dev/null +++ b/tests/view_tests/tests/test_default_content_type.py @@ -0,0 +1,44 @@ +import sys +from types import ModuleType + +from django.conf import Settings +from django.test import SimpleTestCase, ignore_warnings +from django.utils.deprecation import RemovedInDjango30Warning + + +class DefaultContentTypeTests(SimpleTestCase): + msg = 'The DEFAULT_CONTENT_TYPE setting is deprecated.' + + @ignore_warnings(category=RemovedInDjango30Warning) + def test_default_content_type_is_text_html(self): + """ + Content-Type of the default error responses is text/html. Refs #20822. + """ + with self.settings(DEFAULT_CONTENT_TYPE='text/xml'): + response = self.client.get('/raises400/') + self.assertEqual(response['Content-Type'], 'text/html') + + response = self.client.get('/raises403/') + self.assertEqual(response['Content-Type'], 'text/html') + + response = self.client.get('/nonexistent_url/') + self.assertEqual(response['Content-Type'], 'text/html') + + response = self.client.get('/server_error/') + self.assertEqual(response['Content-Type'], 'text/html') + + def test_override_settings_warning(self): + with self.assertRaisesMessage(RemovedInDjango30Warning, self.msg): + with self.settings(DEFAULT_CONTENT_TYPE='text/xml'): + pass + + def test_settings_init_warning(self): + settings_module = ModuleType('fake_settings_module') + settings_module.DEFAULT_CONTENT_TYPE = 'text/xml' + settings_module.SECRET_KEY = 'abc' + sys.modules['fake_settings_module'] = settings_module + try: + with self.assertRaisesMessage(RemovedInDjango30Warning, self.msg): + Settings('fake_settings_module') + finally: + del sys.modules['fake_settings_module'] diff --git a/tests/view_tests/tests/test_defaults.py b/tests/view_tests/tests/test_defaults.py index 62c3fc7619..3ab109a57c 100644 --- a/tests/view_tests/tests/test_defaults.py +++ b/tests/view_tests/tests/test_defaults.py @@ -104,23 +104,6 @@ class DefaultsTests(TestCase): self.assertTrue(getattr(article.get_absolute_url, 'purge', False), 'The attributes of the original get_absolute_url must be added.') - @override_settings(DEFAULT_CONTENT_TYPE="text/xml") - def test_default_content_type_is_text_html(self): - """ - Content-Type of the default error responses is text/html. Refs #20822. - """ - response = self.client.get('/raises400/') - self.assertEqual(response['Content-Type'], 'text/html') - - response = self.client.get('/raises403/') - self.assertEqual(response['Content-Type'], 'text/html') - - response = self.client.get('/nonexistent_url/') - self.assertEqual(response['Content-Type'], 'text/html') - - response = self.client.get('/server_error/') - self.assertEqual(response['Content-Type'], 'text/html') - def test_custom_templates_wrong(self): """ Default error views should raise TemplateDoesNotExist when passed a