Skip to content

Commit a4931cd

Browse files
authored
Refs #34380 -- Added FORMS_URLFIELD_ASSUME_HTTPS transitional setting.
This allows early adoption of the new default "https".
1 parent 5f9e5c1 commit a4931cd

File tree

9 files changed

+113
-12
lines changed

9 files changed

+113
-12
lines changed

django/conf/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
import django
1717
from django.conf import global_settings
1818
from django.core.exceptions import ImproperlyConfigured
19+
from django.utils.deprecation import RemovedInDjango60Warning
1920
from django.utils.functional import LazyObject, empty
2021

2122
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
2223
DEFAULT_STORAGE_ALIAS = "default"
2324
STATICFILES_STORAGE_ALIAS = "staticfiles"
2425

26+
# RemovedInDjango60Warning.
27+
FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG = (
28+
"The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated."
29+
)
30+
2531

2632
class SettingsReference(str):
2733
"""
@@ -180,6 +186,12 @@ def __init__(self, settings_module):
180186
setattr(self, setting, setting_value)
181187
self._explicit_settings.add(setting)
182188

189+
if self.is_overridden("FORMS_URLFIELD_ASSUME_HTTPS"):
190+
warnings.warn(
191+
FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG,
192+
RemovedInDjango60Warning,
193+
)
194+
183195
if hasattr(time, "tzset") and self.TIME_ZONE:
184196
# When we can, attempt to validate the timezone. If we can't find
185197
# this file, no check happens and it's harmless.
@@ -224,6 +236,11 @@ def __getattr__(self, name):
224236

225237
def __setattr__(self, name, value):
226238
self._deleted.discard(name)
239+
if name == "FORMS_URLFIELD_ASSUME_HTTPS":
240+
warnings.warn(
241+
FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG,
242+
RemovedInDjango60Warning,
243+
)
227244
super().__setattr__(name, value)
228245

229246
def __delattr__(self, name):

django/conf/global_settings.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ def gettext_noop(s):
216216
# Default form rendering class.
217217
FORM_RENDERER = "django.forms.renderers.DjangoTemplates"
218218

219+
# RemovedInDjango60Warning: It's a transitional setting helpful in early
220+
# adoption of "https" as the new default value of forms.URLField.assume_scheme.
221+
# Set to True to assume "https" during the Django 5.x release cycle.
222+
FORMS_URLFIELD_ASSUME_HTTPS = False
223+
219224
# Default email address to use for various automated correspondence from
220225
# the site managers.
221226
DEFAULT_FROM_EMAIL = "webmaster@localhost"

django/forms/fields.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from io import BytesIO
1616
from urllib.parse import urlsplit, urlunsplit
1717

18+
from django.conf import settings
1819
from django.core import validators
1920
from django.core.exceptions import ValidationError
2021
from django.forms.boundfield import BoundField
@@ -762,14 +763,19 @@ class URLField(CharField):
762763

763764
def __init__(self, *, assume_scheme=None, **kwargs):
764765
if assume_scheme is None:
765-
warnings.warn(
766-
"The default scheme will be changed from 'http' to 'https' in Django "
767-
"6.0. Pass the forms.URLField.assume_scheme argument to silence this "
768-
"warning.",
769-
RemovedInDjango60Warning,
770-
stacklevel=2,
771-
)
772-
assume_scheme = "http"
766+
if settings.FORMS_URLFIELD_ASSUME_HTTPS:
767+
assume_scheme = "https"
768+
else:
769+
warnings.warn(
770+
"The default scheme will be changed from 'http' to 'https' in "
771+
"Django 6.0. Pass the forms.URLField.assume_scheme argument to "
772+
"silence this warning, or set the FORMS_URLFIELD_ASSUME_HTTPS "
773+
"transitional setting to True to opt into using 'https' as the new "
774+
"default scheme.",
775+
RemovedInDjango60Warning,
776+
stacklevel=2,
777+
)
778+
assume_scheme = "http"
773779
# RemovedInDjango60Warning: When the deprecation ends, replace with:
774780
# self.assume_scheme = assume_scheme or "https"
775781
self.assume_scheme = assume_scheme

docs/internals/deprecation.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ details on these changes.
5353
* ``get_prefetcher()`` and ``prefetch_related_objects()`` will no longer
5454
fallback to ``get_prefetch_queryset()``.
5555

56+
* The ``FORMS_URLFIELD_ASSUME_HTTPS`` transitional setting will be removed.
57+
5658
See the :ref:`Django 5.1 release notes <deprecated-features-5.1>` for more
5759
details on these changes.
5860

docs/ref/forms/fields.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,9 @@ For each field, we describe the default widget used if you don't specify
11551155
.. deprecated:: 5.0
11561156

11571157
The default value for ``assume_scheme`` will change from ``"http"`` to
1158-
``"https"`` in Django 6.0.
1158+
``"https"`` in Django 6.0. Set :setting:`FORMS_URLFIELD_ASSUME_HTTPS`
1159+
transitional setting to ``True`` to opt into using ``"https"`` during
1160+
the Django 5.x release cycle.
11591161

11601162
``UUIDField``
11611163
-------------

docs/ref/settings.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,20 @@ renderers are:
16751675
* ``'``:class:`django.forms.renderers.Jinja2`\ ``'``
16761676
* ``'``:class:`django.forms.renderers.TemplatesSetting`\ ``'``
16771677

1678+
.. setting:: FORMS_URLFIELD_ASSUME_HTTPS
1679+
1680+
``FORMS_URLFIELD_ASSUME_HTTPS``
1681+
-------------------------------
1682+
1683+
.. versionadded:: 5.0
1684+
.. deprecated:: 5.0
1685+
1686+
Default: ``False``
1687+
1688+
Set this transitional setting to ``True`` to opt into using ``"https"`` as the
1689+
new default value of :attr:`URLField.assume_scheme
1690+
<django.forms.URLField.assume_scheme>` during the Django 5.x release cycle.
1691+
16781692
.. setting:: FORMAT_MODULE_PATH
16791693

16801694
``FORMAT_MODULE_PATH``
@@ -3635,6 +3649,7 @@ File uploads
36353649
Forms
36363650
-----
36373651
* :setting:`FORM_RENDERER`
3652+
* :setting:`FORMS_URLFIELD_ASSUME_HTTPS`
36383653

36393654
Globalization (``i18n``/``l10n``)
36403655
---------------------------------

docs/releases/5.0.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,11 @@ Miscellaneous
612612
* The ``ForeignObject.get_reverse_joining_columns()`` method is deprecated.
613613

614614
* The default scheme for ``forms.URLField`` will change from ``"http"`` to
615-
``"https"`` in Django 6.0.
615+
``"https"`` in Django 6.0. Set :setting:`FORMS_URLFIELD_ASSUME_HTTPS`
616+
transitional setting to ``True`` to opt into assuming ``"https"`` during the
617+
Django 5.x release cycle.
618+
619+
* ``FORMS_URLFIELD_ASSUME_HTTPS`` transitional setting is deprecated.
616620

617621
* Support for calling ``format_html()`` without passing args or kwargs will be
618622
removed.

tests/forms_tests/field_tests/test_urlfield.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import sys
2+
from types import ModuleType
3+
4+
from django.conf import FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, Settings, settings
15
from django.core.exceptions import ValidationError
26
from django.forms import URLField
37
from django.test import SimpleTestCase, ignore_warnings
@@ -155,8 +159,41 @@ class URLFieldAssumeSchemeDeprecationTest(FormFieldAssertionsMixin, SimpleTestCa
155159
def test_urlfield_raises_warning(self):
156160
msg = (
157161
"The default scheme will be changed from 'http' to 'https' in Django 6.0. "
158-
"Pass the forms.URLField.assume_scheme argument to silence this warning."
162+
"Pass the forms.URLField.assume_scheme argument to silence this warning, "
163+
"or set the FORMS_URLFIELD_ASSUME_HTTPS transitional setting to True to "
164+
"opt into using 'https' as the new default scheme."
159165
)
160166
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
161167
f = URLField()
162168
self.assertEqual(f.clean("example.com"), "http://example.com")
169+
170+
@ignore_warnings(category=RemovedInDjango60Warning)
171+
def test_urlfield_forms_urlfield_assume_https(self):
172+
with self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True):
173+
f = URLField()
174+
self.assertEqual(f.clean("example.com"), "https://example.com")
175+
f = URLField(assume_scheme="http")
176+
self.assertEqual(f.clean("example.com"), "http://example.com")
177+
178+
def test_override_forms_urlfield_assume_https_setting_warning(self):
179+
msg = FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG
180+
with self.assertRaisesMessage(RemovedInDjango60Warning, msg):
181+
# Changing FORMS_URLFIELD_ASSUME_HTTPS via self.settings() raises a
182+
# deprecation warning.
183+
with self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True):
184+
pass
185+
186+
def test_settings_init_forms_urlfield_assume_https_warning(self):
187+
settings_module = ModuleType("fake_settings_module")
188+
settings_module.FORMS_URLFIELD_ASSUME_HTTPS = True
189+
sys.modules["fake_settings_module"] = settings_module
190+
msg = FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG
191+
try:
192+
with self.assertRaisesMessage(RemovedInDjango60Warning, msg):
193+
Settings("fake_settings_module")
194+
finally:
195+
del sys.modules["fake_settings_module"]
196+
197+
def test_access_forms_urlfield_assume_https(self):
198+
# Warning is not raised on access.
199+
self.assertEqual(settings.FORMS_URLFIELD_ASSUME_HTTPS, False)

tests/model_forms/tests.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2930,7 +2930,8 @@ def test_url_modelform_assume_scheme_warning(self):
29302930
msg = (
29312931
"The default scheme will be changed from 'http' to 'https' in Django "
29322932
"6.0. Pass the forms.URLField.assume_scheme argument to silence this "
2933-
"warning."
2933+
"warning, or set the FORMS_URLFIELD_ASSUME_HTTPS transitional setting to "
2934+
"True to opt into using 'https' as the new default scheme."
29342935
)
29352936
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
29362937

@@ -2939,6 +2940,18 @@ class Meta:
29392940
model = Homepage
29402941
fields = "__all__"
29412942

2943+
def test_url_modelform_assume_scheme_early_adopt_https(self):
2944+
msg = "The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated."
2945+
with (
2946+
self.assertWarnsMessage(RemovedInDjango60Warning, msg),
2947+
self.settings(FORMS_URLFIELD_ASSUME_HTTPS=True),
2948+
):
2949+
2950+
class HomepageForm(forms.ModelForm):
2951+
class Meta:
2952+
model = Homepage
2953+
fields = "__all__"
2954+
29422955
def test_modelform_non_editable_field(self):
29432956
"""
29442957
When explicitly including a non-editable field in a ModelForm, the

0 commit comments

Comments
 (0)