mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[5.0.x] Refs #34380 -- Added FORMS_URLFIELD_ASSUME_HTTPS transitional setting.
This allows early adoption of the new default "https".
Backport of a4931cd75a from main.
			
			
This commit is contained in:
		| @@ -16,7 +16,7 @@ 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 RemovedInDjango51Warning | from django.utils.deprecation import RemovedInDjango51Warning, RemovedInDjango60Warning | ||||||
| from django.utils.functional import LazyObject, empty | from django.utils.functional import LazyObject, empty | ||||||
|  |  | ||||||
| ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" | ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" | ||||||
| @@ -31,6 +31,11 @@ STATICFILES_STORAGE_DEPRECATED_MSG = ( | |||||||
|     "The STATICFILES_STORAGE setting is deprecated. Use STORAGES instead." |     "The STATICFILES_STORAGE setting is deprecated. Use STORAGES instead." | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | # RemovedInDjango60Warning. | ||||||
|  | FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG = ( | ||||||
|  |     "The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated." | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class SettingsReference(str): | class SettingsReference(str): | ||||||
|     """ |     """ | ||||||
| @@ -205,6 +210,12 @@ class Settings: | |||||||
|                 setattr(self, setting, setting_value) |                 setattr(self, setting, setting_value) | ||||||
|                 self._explicit_settings.add(setting) |                 self._explicit_settings.add(setting) | ||||||
|  |  | ||||||
|  |         if self.is_overridden("FORMS_URLFIELD_ASSUME_HTTPS"): | ||||||
|  |             warnings.warn( | ||||||
|  |                 FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, | ||||||
|  |                 RemovedInDjango60Warning, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|         if hasattr(time, "tzset") and self.TIME_ZONE: |         if hasattr(time, "tzset") and self.TIME_ZONE: | ||||||
|             # When we can, attempt to validate the timezone. If we can't find |             # When we can, attempt to validate the timezone. If we can't find | ||||||
|             # this file, no check happens and it's harmless. |             # this file, no check happens and it's harmless. | ||||||
| @@ -293,6 +304,11 @@ class UserSettingsHolder: | |||||||
|                 "BACKEND": self.STATICFILES_STORAGE |                 "BACKEND": self.STATICFILES_STORAGE | ||||||
|             } |             } | ||||||
|             warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) |             warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) | ||||||
|  |         if name == "FORMS_URLFIELD_ASSUME_HTTPS": | ||||||
|  |             warnings.warn( | ||||||
|  |                 FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, | ||||||
|  |                 RemovedInDjango60Warning, | ||||||
|  |             ) | ||||||
|         super().__setattr__(name, value) |         super().__setattr__(name, value) | ||||||
|         # RemovedInDjango51Warning. |         # RemovedInDjango51Warning. | ||||||
|         if name == "STORAGES": |         if name == "STORAGES": | ||||||
|   | |||||||
| @@ -216,6 +216,11 @@ TEMPLATES = [] | |||||||
| # Default form rendering class. | # Default form rendering class. | ||||||
| FORM_RENDERER = "django.forms.renderers.DjangoTemplates" | FORM_RENDERER = "django.forms.renderers.DjangoTemplates" | ||||||
|  |  | ||||||
|  | # RemovedInDjango60Warning: It's a transitional setting helpful in early | ||||||
|  | # adoption of "https" as the new default value of forms.URLField.assume_scheme. | ||||||
|  | # Set to True to assume "https" during the Django 5.x release cycle. | ||||||
|  | FORMS_URLFIELD_ASSUME_HTTPS = False | ||||||
|  |  | ||||||
| # Default email address to use for various automated correspondence from | # Default email address to use for various automated correspondence from | ||||||
| # the site managers. | # the site managers. | ||||||
| DEFAULT_FROM_EMAIL = "webmaster@localhost" | DEFAULT_FROM_EMAIL = "webmaster@localhost" | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ from decimal import Decimal, DecimalException | |||||||
| from io import BytesIO | from io import BytesIO | ||||||
| from urllib.parse import urlsplit, urlunsplit | from urllib.parse import urlsplit, urlunsplit | ||||||
|  |  | ||||||
|  | from django.conf import settings | ||||||
| from django.core import validators | from django.core import validators | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.forms.boundfield import BoundField | from django.forms.boundfield import BoundField | ||||||
| @@ -762,14 +763,19 @@ class URLField(CharField): | |||||||
|  |  | ||||||
|     def __init__(self, *, assume_scheme=None, **kwargs): |     def __init__(self, *, assume_scheme=None, **kwargs): | ||||||
|         if assume_scheme is None: |         if assume_scheme is None: | ||||||
|             warnings.warn( |             if settings.FORMS_URLFIELD_ASSUME_HTTPS: | ||||||
|                 "The default scheme will be changed from 'http' to 'https' in Django " |                 assume_scheme = "https" | ||||||
|                 "6.0. Pass the forms.URLField.assume_scheme argument to silence this " |             else: | ||||||
|                 "warning.", |                 warnings.warn( | ||||||
|                 RemovedInDjango60Warning, |                     "The default scheme will be changed from 'http' to 'https' in " | ||||||
|                 stacklevel=2, |                     "Django 6.0. Pass the forms.URLField.assume_scheme argument to " | ||||||
|             ) |                     "silence this warning, or set the FORMS_URLFIELD_ASSUME_HTTPS " | ||||||
|             assume_scheme = "http" |                     "transitional setting to True to opt into using 'https' as the new " | ||||||
|  |                     "default scheme.", | ||||||
|  |                     RemovedInDjango60Warning, | ||||||
|  |                     stacklevel=2, | ||||||
|  |                 ) | ||||||
|  |                 assume_scheme = "http" | ||||||
|         # RemovedInDjango60Warning: When the deprecation ends, replace with: |         # RemovedInDjango60Warning: When the deprecation ends, replace with: | ||||||
|         # self.assume_scheme = assume_scheme or "https" |         # self.assume_scheme = assume_scheme or "https" | ||||||
|         self.assume_scheme = assume_scheme |         self.assume_scheme = assume_scheme | ||||||
|   | |||||||
| @@ -53,6 +53,8 @@ details on these changes. | |||||||
| * ``get_prefetcher()`` and ``prefetch_related_objects()`` will no longer | * ``get_prefetcher()`` and ``prefetch_related_objects()`` will no longer | ||||||
|   fallback to ``get_prefetch_queryset()``. |   fallback to ``get_prefetch_queryset()``. | ||||||
|  |  | ||||||
|  | * The ``FORMS_URLFIELD_ASSUME_HTTPS`` transitional setting will be removed. | ||||||
|  |  | ||||||
| .. _deprecation-removed-in-5.1: | .. _deprecation-removed-in-5.1: | ||||||
|  |  | ||||||
| 5.1 | 5.1 | ||||||
|   | |||||||
| @@ -1154,7 +1154,9 @@ For each field, we describe the default widget used if you don't specify | |||||||
|     .. deprecated:: 5.0 |     .. deprecated:: 5.0 | ||||||
|  |  | ||||||
|         The default value for ``assume_scheme`` will change from ``"http"`` to |         The default value for ``assume_scheme`` will change from ``"http"`` to | ||||||
|         ``"https"`` in Django 6.0. |         ``"https"`` in Django 6.0. Set :setting:`FORMS_URLFIELD_ASSUME_HTTPS` | ||||||
|  |         transitional setting to ``True`` to opt into using ``"https"`` during | ||||||
|  |         the Django 5.x release cycle. | ||||||
|  |  | ||||||
| ``UUIDField`` | ``UUIDField`` | ||||||
| ------------- | ------------- | ||||||
|   | |||||||
| @@ -1693,6 +1693,20 @@ renderers are: | |||||||
| * ``'``:class:`django.forms.renderers.Jinja2`\ ``'`` | * ``'``:class:`django.forms.renderers.Jinja2`\ ``'`` | ||||||
| * ``'``:class:`django.forms.renderers.TemplatesSetting`\ ``'`` | * ``'``:class:`django.forms.renderers.TemplatesSetting`\ ``'`` | ||||||
|  |  | ||||||
|  | .. setting:: FORMS_URLFIELD_ASSUME_HTTPS | ||||||
|  |  | ||||||
|  | ``FORMS_URLFIELD_ASSUME_HTTPS`` | ||||||
|  | ------------------------------- | ||||||
|  |  | ||||||
|  | .. versionadded:: 5.0 | ||||||
|  | .. deprecated:: 5.0 | ||||||
|  |  | ||||||
|  | Default: ``False`` | ||||||
|  |  | ||||||
|  | Set this transitional setting to ``True`` to opt into using ``"https"`` as the | ||||||
|  | new default value of :attr:`URLField.assume_scheme | ||||||
|  | <django.forms.URLField.assume_scheme>` during the Django 5.x release cycle. | ||||||
|  |  | ||||||
| .. setting:: FORMAT_MODULE_PATH | .. setting:: FORMAT_MODULE_PATH | ||||||
|  |  | ||||||
| ``FORMAT_MODULE_PATH`` | ``FORMAT_MODULE_PATH`` | ||||||
| @@ -3677,6 +3691,7 @@ File uploads | |||||||
| Forms | Forms | ||||||
| ----- | ----- | ||||||
| * :setting:`FORM_RENDERER` | * :setting:`FORM_RENDERER` | ||||||
|  | * :setting:`FORMS_URLFIELD_ASSUME_HTTPS` | ||||||
|  |  | ||||||
| Globalization (``i18n``/``l10n``) | Globalization (``i18n``/``l10n``) | ||||||
| --------------------------------- | --------------------------------- | ||||||
|   | |||||||
| @@ -612,7 +612,11 @@ Miscellaneous | |||||||
| * The ``ForeignObject.get_reverse_joining_columns()`` method is deprecated. | * The ``ForeignObject.get_reverse_joining_columns()`` method is deprecated. | ||||||
|  |  | ||||||
| * The default scheme for ``forms.URLField`` will change from ``"http"`` to | * The default scheme for ``forms.URLField`` will change from ``"http"`` to | ||||||
|   ``"https"`` in Django 6.0. |   ``"https"`` in Django 6.0. Set :setting:`FORMS_URLFIELD_ASSUME_HTTPS` | ||||||
|  |   transitional setting to ``True`` to opt into assuming ``"https"`` during the | ||||||
|  |   Django 5.x release cycle. | ||||||
|  |  | ||||||
|  | * ``FORMS_URLFIELD_ASSUME_HTTPS`` transitional setting is deprecated. | ||||||
|  |  | ||||||
| * Support for calling ``format_html()`` without passing args or kwargs will be | * Support for calling ``format_html()`` without passing args or kwargs will be | ||||||
|   removed. |   removed. | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | import sys | ||||||
|  | from types import ModuleType | ||||||
|  |  | ||||||
|  | from django.conf import FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, Settings, settings | ||||||
| from django.core.exceptions import ValidationError | from django.core.exceptions import ValidationError | ||||||
| from django.forms import URLField | from django.forms import URLField | ||||||
| from django.test import SimpleTestCase, ignore_warnings | from django.test import SimpleTestCase, ignore_warnings | ||||||
| @@ -155,8 +159,41 @@ class URLFieldAssumeSchemeDeprecationTest(FormFieldAssertionsMixin, SimpleTestCa | |||||||
|     def test_urlfield_raises_warning(self): |     def test_urlfield_raises_warning(self): | ||||||
|         msg = ( |         msg = ( | ||||||
|             "The default scheme will be changed from 'http' to 'https' in Django 6.0. " |             "The default scheme will be changed from 'http' to 'https' in Django 6.0. " | ||||||
|             "Pass the forms.URLField.assume_scheme argument to silence this warning." |             "Pass the forms.URLField.assume_scheme argument to silence this warning, " | ||||||
|  |             "or set the FORMS_URLFIELD_ASSUME_HTTPS transitional setting to True to " | ||||||
|  |             "opt into using 'https' as the new default scheme." | ||||||
|         ) |         ) | ||||||
|         with self.assertWarnsMessage(RemovedInDjango60Warning, msg): |         with self.assertWarnsMessage(RemovedInDjango60Warning, msg): | ||||||
|             f = URLField() |             f = URLField() | ||||||
|             self.assertEqual(f.clean("example.com"), "http://example.com") |             self.assertEqual(f.clean("example.com"), "http://example.com") | ||||||
|  |  | ||||||
|  |     @ignore_warnings(category=RemovedInDjango60Warning) | ||||||
|  |     def test_urlfield_forms_urlfield_assume_https(self): | ||||||
|  |         with self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True): | ||||||
|  |             f = URLField() | ||||||
|  |             self.assertEqual(f.clean("example.com"), "https://example.com") | ||||||
|  |             f = URLField(assume_scheme="http") | ||||||
|  |             self.assertEqual(f.clean("example.com"), "http://example.com") | ||||||
|  |  | ||||||
|  |     def test_override_forms_urlfield_assume_https_setting_warning(self): | ||||||
|  |         msg = FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG | ||||||
|  |         with self.assertRaisesMessage(RemovedInDjango60Warning, msg): | ||||||
|  |             # Changing FORMS_URLFIELD_ASSUME_HTTPS via self.settings() raises a | ||||||
|  |             # deprecation warning. | ||||||
|  |             with self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True): | ||||||
|  |                 pass | ||||||
|  |  | ||||||
|  |     def test_settings_init_forms_urlfield_assume_https_warning(self): | ||||||
|  |         settings_module = ModuleType("fake_settings_module") | ||||||
|  |         settings_module.FORMS_URLFIELD_ASSUME_HTTPS = True | ||||||
|  |         sys.modules["fake_settings_module"] = settings_module | ||||||
|  |         msg = FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG | ||||||
|  |         try: | ||||||
|  |             with self.assertRaisesMessage(RemovedInDjango60Warning, msg): | ||||||
|  |                 Settings("fake_settings_module") | ||||||
|  |         finally: | ||||||
|  |             del sys.modules["fake_settings_module"] | ||||||
|  |  | ||||||
|  |     def test_access_forms_urlfield_assume_https(self): | ||||||
|  |         # Warning is not raised on access. | ||||||
|  |         self.assertEqual(settings.FORMS_URLFIELD_ASSUME_HTTPS, False) | ||||||
|   | |||||||
| @@ -2929,7 +2929,8 @@ class ModelOtherFieldTests(SimpleTestCase): | |||||||
|         msg = ( |         msg = ( | ||||||
|             "The default scheme will be changed from 'http' to 'https' in Django " |             "The default scheme will be changed from 'http' to 'https' in Django " | ||||||
|             "6.0. Pass the forms.URLField.assume_scheme argument to silence this " |             "6.0. Pass the forms.URLField.assume_scheme argument to silence this " | ||||||
|             "warning." |             "warning, or set the FORMS_URLFIELD_ASSUME_HTTPS transitional setting to " | ||||||
|  |             "True to opt into using 'https' as the new default scheme." | ||||||
|         ) |         ) | ||||||
|         with self.assertWarnsMessage(RemovedInDjango60Warning, msg): |         with self.assertWarnsMessage(RemovedInDjango60Warning, msg): | ||||||
|  |  | ||||||
| @@ -2938,6 +2939,18 @@ class ModelOtherFieldTests(SimpleTestCase): | |||||||
|                     model = Homepage |                     model = Homepage | ||||||
|                     fields = "__all__" |                     fields = "__all__" | ||||||
|  |  | ||||||
|  |     def test_url_modelform_assume_scheme_early_adopt_https(self): | ||||||
|  |         msg = "The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated." | ||||||
|  |         with ( | ||||||
|  |             self.assertWarnsMessage(RemovedInDjango60Warning, msg), | ||||||
|  |             self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True), | ||||||
|  |         ): | ||||||
|  |  | ||||||
|  |             class HomepageForm(forms.ModelForm): | ||||||
|  |                 class Meta: | ||||||
|  |                     model = Homepage | ||||||
|  |                     fields = "__all__" | ||||||
|  |  | ||||||
|     def test_modelform_non_editable_field(self): |     def test_modelform_non_editable_field(self): | ||||||
|         """ |         """ | ||||||
|         When explicitly including a non-editable field in a ModelForm, the |         When explicitly including a non-editable field in a ModelForm, the | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user