mirror of https://github.com/django/django.git
Refs #27829 -- Removed settings.DEFAULT_CONTENT_TYPE per deprecation timeline.
This commit is contained in:
parent
573ec714e5
commit
8045dff98c
|
@ -16,14 +16,11 @@ from pathlib import Path
|
||||||
import django
|
import django
|
||||||
from django.conf import global_settings
|
from django.conf import global_settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.deprecation import (
|
from django.utils.deprecation import RemovedInDjango31Warning
|
||||||
RemovedInDjango30Warning, RemovedInDjango31Warning,
|
|
||||||
)
|
|
||||||
from django.utils.functional import LazyObject, empty
|
from django.utils.functional import LazyObject, empty
|
||||||
|
|
||||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||||
|
|
||||||
DEFAULT_CONTENT_TYPE_DEPRECATED_MSG = 'The DEFAULT_CONTENT_TYPE setting is deprecated.'
|
|
||||||
FILE_CHARSET_DEPRECATED_MSG = (
|
FILE_CHARSET_DEPRECATED_MSG = (
|
||||||
'The FILE_CHARSET setting is deprecated. Starting with Django 3.1, all '
|
'The FILE_CHARSET setting is deprecated. Starting with Django 3.1, all '
|
||||||
'files read from disk must be UTF-8 encoded.'
|
'files read from disk must be UTF-8 encoded.'
|
||||||
|
@ -115,20 +112,6 @@ class LazySettings(LazyObject):
|
||||||
"""Return True if the settings have already been configured."""
|
"""Return True if the settings have already been configured."""
|
||||||
return self._wrapped is not empty
|
return self._wrapped is not empty
|
||||||
|
|
||||||
@property
|
|
||||||
def DEFAULT_CONTENT_TYPE(self):
|
|
||||||
stack = traceback.extract_stack()
|
|
||||||
# Show a warning if the setting is used outside of Django.
|
|
||||||
# Stack index: -1 this line, -2 the caller.
|
|
||||||
filename, _line_number, _function_name, _text = stack[-2]
|
|
||||||
if not filename.startswith(os.path.dirname(django.__file__)):
|
|
||||||
warnings.warn(
|
|
||||||
DEFAULT_CONTENT_TYPE_DEPRECATED_MSG,
|
|
||||||
RemovedInDjango30Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return self.__getattr__('DEFAULT_CONTENT_TYPE')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def FILE_CHARSET(self):
|
def FILE_CHARSET(self):
|
||||||
stack = traceback.extract_stack()
|
stack = traceback.extract_stack()
|
||||||
|
@ -175,8 +158,6 @@ class Settings:
|
||||||
if not self.SECRET_KEY:
|
if not self.SECRET_KEY:
|
||||||
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
|
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
|
||||||
|
|
||||||
if self.is_overridden('DEFAULT_CONTENT_TYPE'):
|
|
||||||
warnings.warn(DEFAULT_CONTENT_TYPE_DEPRECATED_MSG, RemovedInDjango30Warning)
|
|
||||||
if self.is_overridden('FILE_CHARSET'):
|
if self.is_overridden('FILE_CHARSET'):
|
||||||
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
|
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
|
||||||
|
|
||||||
|
@ -223,9 +204,7 @@ class UserSettingsHolder:
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
self._deleted.discard(name)
|
self._deleted.discard(name)
|
||||||
if name == 'DEFAULT_CONTENT_TYPE':
|
if name == 'FILE_CHARSET':
|
||||||
warnings.warn(DEFAULT_CONTENT_TYPE_DEPRECATED_MSG, RemovedInDjango30Warning)
|
|
||||||
elif name == 'FILE_CHARSET':
|
|
||||||
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
|
warnings.warn(FILE_CHARSET_DEPRECATED_MSG, RemovedInDjango31Warning)
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
|
|
|
@ -164,10 +164,8 @@ USE_L10N = False
|
||||||
# notifications and other various emails.
|
# notifications and other various emails.
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
# Default content type and charset to use for all HttpResponse objects, if a
|
# Default charset to use for all HttpResponse objects, if a MIME type isn't
|
||||||
# MIME type isn't manually specified. These are used to construct the
|
# manually specified. It's used to construct the Content-Type header.
|
||||||
# Content-Type header.
|
|
||||||
DEFAULT_CONTENT_TYPE = 'text/html'
|
|
||||||
DEFAULT_CHARSET = 'utf-8'
|
DEFAULT_CHARSET = 'utf-8'
|
||||||
|
|
||||||
# Encoding of files read from disk (template and initial SQL files).
|
# Encoding of files read from disk (template and initial SQL files).
|
||||||
|
|
|
@ -57,8 +57,7 @@ class HttpResponseBase:
|
||||||
self._reason_phrase = reason
|
self._reason_phrase = reason
|
||||||
self._charset = charset
|
self._charset = charset
|
||||||
if content_type is None:
|
if content_type is None:
|
||||||
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
|
content_type = 'text/html; charset=%s' % self.charset
|
||||||
self.charset)
|
|
||||||
self['Content-Type'] = content_type
|
self['Content-Type'] = content_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -427,7 +426,7 @@ class FileResponse(StreamingHttpResponse):
|
||||||
elif hasattr(filelike, 'getbuffer'):
|
elif hasattr(filelike, 'getbuffer'):
|
||||||
self['Content-Length'] = filelike.getbuffer().nbytes
|
self['Content-Length'] = filelike.getbuffer().nbytes
|
||||||
|
|
||||||
if self.get('Content-Type', '').startswith(settings.DEFAULT_CONTENT_TYPE):
|
if self.get('Content-Type', '').startswith('text/html'):
|
||||||
if filename:
|
if filename:
|
||||||
content_type, encoding = mimetypes.guess_type(filename)
|
content_type, encoding = mimetypes.guess_type(filename)
|
||||||
# Encoding isn't set to prevent browsers from automatically
|
# Encoding isn't set to prevent browsers from automatically
|
||||||
|
|
|
@ -47,7 +47,7 @@ def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
|
||||||
try:
|
try:
|
||||||
template = loader.get_template(template_name)
|
template = loader.get_template(template_name)
|
||||||
body = template.render(context, request)
|
body = template.render(context, request)
|
||||||
content_type = None # Django will use DEFAULT_CONTENT_TYPE
|
content_type = None # Django will use 'text/html'.
|
||||||
except TemplateDoesNotExist:
|
except TemplateDoesNotExist:
|
||||||
if template_name != ERROR_404_TEMPLATE_NAME:
|
if template_name != ERROR_404_TEMPLATE_NAME:
|
||||||
# Reraise if it's a missing custom template.
|
# Reraise if it's a missing custom template.
|
||||||
|
|
|
@ -83,7 +83,7 @@ Simple mixins
|
||||||
|
|
||||||
The content type to use for the response. ``content_type`` is passed
|
The content type to use for the response. ``content_type`` is passed
|
||||||
as a keyword argument to ``response_class``. Default is ``None`` --
|
as a keyword argument to ``response_class``. Default is ``None`` --
|
||||||
meaning that Django uses :setting:`DEFAULT_CONTENT_TYPE`.
|
meaning that Django uses ``'text/html'``.
|
||||||
|
|
||||||
**Methods**
|
**Methods**
|
||||||
|
|
||||||
|
|
|
@ -748,7 +748,7 @@ Methods
|
||||||
|
|
||||||
``content_type`` is the MIME type optionally completed by a character set
|
``content_type`` is the MIME type optionally completed by a character set
|
||||||
encoding and is used to fill the HTTP ``Content-Type`` header. If not
|
encoding and is used to fill the HTTP ``Content-Type`` header. If not
|
||||||
specified, it is formed by the :setting:`DEFAULT_CONTENT_TYPE` and
|
specified, it is formed by ``'text/html'`` and the
|
||||||
:setting:`DEFAULT_CHARSET` settings, by default: "`text/html; charset=utf-8`".
|
:setting:`DEFAULT_CHARSET` settings, by default: "`text/html; charset=utf-8`".
|
||||||
|
|
||||||
``status`` is the :rfc:`HTTP status code <7231#section-6>` for the response.
|
``status`` is the :rfc:`HTTP status code <7231#section-6>` for the response.
|
||||||
|
|
|
@ -1195,24 +1195,7 @@ See also :setting:`NUMBER_GROUPING`, :setting:`THOUSAND_SEPARATOR` and
|
||||||
Default: ``'utf-8'``
|
Default: ``'utf-8'``
|
||||||
|
|
||||||
Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't
|
Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't
|
||||||
manually specified. Used with :setting:`DEFAULT_CONTENT_TYPE` to construct the
|
manually specified. Used when constructing the ``Content-Type`` header.
|
||||||
``Content-Type`` header.
|
|
||||||
|
|
||||||
.. setting:: DEFAULT_CONTENT_TYPE
|
|
||||||
|
|
||||||
``DEFAULT_CONTENT_TYPE``
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Default: ``'text/html'``
|
|
||||||
|
|
||||||
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
|
.. setting:: DEFAULT_EXCEPTION_REPORTER_FILTER
|
||||||
|
|
||||||
|
@ -3436,7 +3419,6 @@ HTTP
|
||||||
* :setting:`DATA_UPLOAD_MAX_MEMORY_SIZE`
|
* :setting:`DATA_UPLOAD_MAX_MEMORY_SIZE`
|
||||||
* :setting:`DATA_UPLOAD_MAX_NUMBER_FIELDS`
|
* :setting:`DATA_UPLOAD_MAX_NUMBER_FIELDS`
|
||||||
* :setting:`DEFAULT_CHARSET`
|
* :setting:`DEFAULT_CHARSET`
|
||||||
* :setting:`DEFAULT_CONTENT_TYPE`
|
|
||||||
* :setting:`DISALLOWED_USER_AGENTS`
|
* :setting:`DISALLOWED_USER_AGENTS`
|
||||||
* :setting:`FORCE_SCRIPT_NAME`
|
* :setting:`FORCE_SCRIPT_NAME`
|
||||||
* :setting:`INTERNAL_IPS`
|
* :setting:`INTERNAL_IPS`
|
||||||
|
|
|
@ -76,7 +76,7 @@ Methods
|
||||||
The value included in the HTTP ``Content-Type`` header, including the
|
The value included in the HTTP ``Content-Type`` header, including the
|
||||||
MIME type specification and the character set encoding. If
|
MIME type specification and the character set encoding. If
|
||||||
``content_type`` is specified, then its value is used. Otherwise,
|
``content_type`` is specified, then its value is used. Otherwise,
|
||||||
:setting:`DEFAULT_CONTENT_TYPE` is used.
|
``'text/html'`` is used.
|
||||||
|
|
||||||
``status``
|
``status``
|
||||||
The HTTP status code for the response.
|
The HTTP status code for the response.
|
||||||
|
@ -171,7 +171,7 @@ Methods
|
||||||
The value included in the HTTP ``Content-Type`` header, including the
|
The value included in the HTTP ``Content-Type`` header, including the
|
||||||
MIME type specification and the character set encoding. If
|
MIME type specification and the character set encoding. If
|
||||||
``content_type`` is specified, then its value is used. Otherwise,
|
``content_type`` is specified, then its value is used. Otherwise,
|
||||||
:setting:`DEFAULT_CONTENT_TYPE` is used.
|
``'text/html'`` is used.
|
||||||
|
|
||||||
``status``
|
``status``
|
||||||
The HTTP status code for the response.
|
The HTTP status code for the response.
|
||||||
|
|
|
@ -240,6 +240,8 @@ to remove usage of these features.
|
||||||
|
|
||||||
* ``django.shortcuts.render_to_response()`` is removed.
|
* ``django.shortcuts.render_to_response()`` is removed.
|
||||||
|
|
||||||
|
* The ``DEFAULT_CONTENT_TYPE`` setting is removed.
|
||||||
|
|
||||||
See :ref:`deprecated-features-2.1` for details on these changes, including how
|
See :ref:`deprecated-features-2.1` for details on these changes, including how
|
||||||
to remove usage of these features.
|
to remove usage of these features.
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ Optional arguments
|
||||||
view will call it just before rendering the template.
|
view will call it just before rendering the template.
|
||||||
|
|
||||||
``content_type``
|
``content_type``
|
||||||
The MIME type to use for the resulting document. Defaults to the value of
|
The MIME type to use for the resulting document. Defaults to
|
||||||
the :setting:`DEFAULT_CONTENT_TYPE` setting.
|
``'text/html'``.
|
||||||
|
|
||||||
``status``
|
``status``
|
||||||
The status code for the response. Defaults to ``200``.
|
The status code for the response. Defaults to ``200``.
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
import sys
|
|
||||||
from types import ModuleType
|
|
||||||
|
|
||||||
from django.conf import DEFAULT_CONTENT_TYPE_DEPRECATED_MSG, Settings, settings
|
|
||||||
from django.test import SimpleTestCase, ignore_warnings
|
|
||||||
from django.utils.deprecation import RemovedInDjango30Warning
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultContentTypeTests(SimpleTestCase):
|
|
||||||
msg = DEFAULT_CONTENT_TYPE_DEPRECATED_MSG
|
|
||||||
|
|
||||||
@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']
|
|
||||||
|
|
||||||
def test_access_warning(self):
|
|
||||||
with self.assertRaisesMessage(RemovedInDjango30Warning, self.msg):
|
|
||||||
settings.DEFAULT_CONTENT_TYPE
|
|
||||||
# Works a second time.
|
|
||||||
with self.assertRaisesMessage(RemovedInDjango30Warning, self.msg):
|
|
||||||
settings.DEFAULT_CONTENT_TYPE
|
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango30Warning)
|
|
||||||
def test_access(self):
|
|
||||||
with self.settings(DEFAULT_CONTENT_TYPE='text/xml'):
|
|
||||||
self.assertEqual(settings.DEFAULT_CONTENT_TYPE, 'text/xml')
|
|
||||||
# Works a second time.
|
|
||||||
self.assertEqual(settings.DEFAULT_CONTENT_TYPE, 'text/xml')
|
|
Loading…
Reference in New Issue