mirror of
https://github.com/django/django.git
synced 2025-03-31 19:46:42 +00:00
Fixed #34380 -- Allowed specifying a default URL scheme in forms.URLField.
This also deprecates "http" as the default scheme.
This commit is contained in:
parent
070cbac0db
commit
7bbbadc693
@ -10,6 +10,7 @@ import operator
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
|
import warnings
|
||||||
from decimal import Decimal, DecimalException
|
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
|
||||||
@ -42,6 +43,7 @@ from django.forms.widgets import (
|
|||||||
)
|
)
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.utils.dateparse import parse_datetime, parse_duration
|
from django.utils.dateparse import parse_datetime, parse_duration
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
from django.utils.duration import duration_string
|
from django.utils.duration import duration_string
|
||||||
from django.utils.ipv6 import clean_ipv6_address
|
from django.utils.ipv6 import clean_ipv6_address
|
||||||
from django.utils.regex_helper import _lazy_re_compile
|
from django.utils.regex_helper import _lazy_re_compile
|
||||||
@ -753,7 +755,19 @@ class URLField(CharField):
|
|||||||
}
|
}
|
||||||
default_validators = [validators.URLValidator()]
|
default_validators = [validators.URLValidator()]
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *, assume_scheme=None, **kwargs):
|
||||||
|
if assume_scheme is None:
|
||||||
|
warnings.warn(
|
||||||
|
"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.",
|
||||||
|
RemovedInDjango60Warning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
assume_scheme = "http"
|
||||||
|
# RemovedInDjango60Warning: When the deprecation ends, replace with:
|
||||||
|
# self.assume_scheme = assume_scheme or "https"
|
||||||
|
self.assume_scheme = assume_scheme
|
||||||
super().__init__(strip=True, **kwargs)
|
super().__init__(strip=True, **kwargs)
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
@ -773,8 +787,8 @@ class URLField(CharField):
|
|||||||
if value:
|
if value:
|
||||||
url_fields = split_url(value)
|
url_fields = split_url(value)
|
||||||
if not url_fields[0]:
|
if not url_fields[0]:
|
||||||
# If no URL scheme given, assume http://
|
# If no URL scheme given, add a scheme.
|
||||||
url_fields[0] = "http"
|
url_fields[0] = self.assume_scheme
|
||||||
if not url_fields[1]:
|
if not url_fields[1]:
|
||||||
# Assume that if no domain is provided, that the path segment
|
# Assume that if no domain is provided, that the path segment
|
||||||
# contains the domain.
|
# contains the domain.
|
||||||
|
@ -32,6 +32,9 @@ details on these changes.
|
|||||||
|
|
||||||
* The ``ForeignObject.get_reverse_joining_columns()`` method will be removed.
|
* The ``ForeignObject.get_reverse_joining_columns()`` method will be removed.
|
||||||
|
|
||||||
|
* The default scheme for ``forms.URLField`` will change from ``"http"`` to
|
||||||
|
``"https"``.
|
||||||
|
|
||||||
.. _deprecation-removed-in-5.1:
|
.. _deprecation-removed-in-5.1:
|
||||||
|
|
||||||
5.1
|
5.1
|
||||||
|
@ -1071,8 +1071,18 @@ For each field, we describe the default widget used if you don't specify
|
|||||||
given value is a valid URL.
|
given value is a valid URL.
|
||||||
* Error message keys: ``required``, ``invalid``
|
* Error message keys: ``required``, ``invalid``
|
||||||
|
|
||||||
Has the optional arguments ``max_length``, ``min_length``, and
|
Has the optional arguments ``max_length``, ``min_length``, ``empty_value``
|
||||||
``empty_value`` which work just as they do for :class:`CharField`.
|
which work just as they do for :class:`CharField`, and ``assume_scheme``
|
||||||
|
that defaults to ``"http"``.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
The ``assume_scheme`` argument was added.
|
||||||
|
|
||||||
|
.. deprecated:: 5.0
|
||||||
|
|
||||||
|
The default value for ``assume_scheme`` will change from ``"http"`` to
|
||||||
|
``"https"`` in Django 6.0.
|
||||||
|
|
||||||
``UUIDField``
|
``UUIDField``
|
||||||
-------------
|
-------------
|
||||||
|
@ -245,6 +245,9 @@ Forms
|
|||||||
:ref:`Choices classes <field-choices-enum-types>` directly instead of
|
:ref:`Choices classes <field-choices-enum-types>` directly instead of
|
||||||
requiring expansion with the ``choices`` attribute.
|
requiring expansion with the ``choices`` attribute.
|
||||||
|
|
||||||
|
* The new ``assume_scheme`` argument for :class:`~django.forms.URLField` allows
|
||||||
|
specifying a default URL scheme.
|
||||||
|
|
||||||
Generic Views
|
Generic Views
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -403,6 +406,9 @@ 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
|
||||||
|
``"https"`` in Django 6.0.
|
||||||
|
|
||||||
Features removed in 5.0
|
Features removed in 5.0
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ from django.forms.utils import ErrorList
|
|||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TestCase,
|
TestCase,
|
||||||
|
ignore_warnings,
|
||||||
modify_settings,
|
modify_settings,
|
||||||
override_settings,
|
override_settings,
|
||||||
skipUnlessDBFeature,
|
skipUnlessDBFeature,
|
||||||
@ -34,6 +35,7 @@ from django.test.utils import override_script_prefix
|
|||||||
from django.urls import NoReverseMatch, resolve, reverse
|
from django.urls import NoReverseMatch, resolve, reverse
|
||||||
from django.utils import formats, translation
|
from django.utils import formats, translation
|
||||||
from django.utils.cache import get_max_age
|
from django.utils.cache import get_max_age
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
from django.utils.encoding import iri_to_uri
|
from django.utils.encoding import iri_to_uri
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
@ -6555,6 +6557,7 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client.force_login(self.superuser)
|
self.client.force_login(self.superuser)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_readonly_get(self):
|
def test_readonly_get(self):
|
||||||
response = self.client.get(reverse("admin:admin_views_post_add"))
|
response = self.client.get(reverse("admin:admin_views_post_add"))
|
||||||
self.assertNotContains(response, 'name="posted"')
|
self.assertNotContains(response, 'name="posted"')
|
||||||
@ -6615,6 +6618,7 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
|
|||||||
)
|
)
|
||||||
self.assertContains(response, "%d amount of cool" % p.pk)
|
self.assertContains(response, "%d amount of cool" % p.pk)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_readonly_text_field(self):
|
def test_readonly_text_field(self):
|
||||||
p = Post.objects.create(
|
p = Post.objects.create(
|
||||||
title="Readonly test",
|
title="Readonly test",
|
||||||
@ -6634,6 +6638,7 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
|
|||||||
# Checking readonly field in inline.
|
# Checking readonly field in inline.
|
||||||
self.assertContains(response, "test<br>link")
|
self.assertContains(response, "test<br>link")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_readonly_post(self):
|
def test_readonly_post(self):
|
||||||
data = {
|
data = {
|
||||||
"title": "Django Got Readonly Fields",
|
"title": "Django Got Readonly Fields",
|
||||||
@ -6774,6 +6779,7 @@ class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
|
|||||||
field = self.get_admin_readonly_field(response, "plotdetails")
|
field = self.get_admin_readonly_field(response, "plotdetails")
|
||||||
self.assertEqual(field.contents(), "-") # default empty value
|
self.assertEqual(field.contents(), "-") # default empty value
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_readonly_field_overrides(self):
|
def test_readonly_field_overrides(self):
|
||||||
"""
|
"""
|
||||||
Regression test for #22087 - ModelForm Meta overrides are ignored by
|
Regression test for #22087 - ModelForm Meta overrides are ignored by
|
||||||
@ -7233,6 +7239,7 @@ class CSSTest(TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client.force_login(self.superuser)
|
self.client.force_login(self.superuser)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_field_prefix_css_classes(self):
|
def test_field_prefix_css_classes(self):
|
||||||
"""
|
"""
|
||||||
Fields have a CSS class name with a 'field-' prefix.
|
Fields have a CSS class name with a 'field-' prefix.
|
||||||
|
@ -22,9 +22,10 @@ from django.db.models import (
|
|||||||
ManyToManyField,
|
ManyToManyField,
|
||||||
UUIDField,
|
UUIDField,
|
||||||
)
|
)
|
||||||
from django.test import SimpleTestCase, TestCase, override_settings
|
from django.test import SimpleTestCase, TestCase, ignore_warnings, override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Advisor,
|
Advisor,
|
||||||
@ -106,6 +107,7 @@ class AdminFormfieldForDBFieldTests(SimpleTestCase):
|
|||||||
def test_TextField(self):
|
def test_TextField(self):
|
||||||
self.assertFormfield(Event, "description", widgets.AdminTextareaWidget)
|
self.assertFormfield(Event, "description", widgets.AdminTextareaWidget)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_URLField(self):
|
def test_URLField(self):
|
||||||
self.assertFormfield(Event, "link", widgets.AdminURLFieldWidget)
|
self.assertFormfield(Event, "link", widgets.AdminURLFieldWidget)
|
||||||
|
|
||||||
@ -320,6 +322,7 @@ class AdminForeignKeyRawIdWidget(TestDataMixin, TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client.force_login(self.superuser)
|
self.client.force_login(self.superuser)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_nonexistent_target_id(self):
|
def test_nonexistent_target_id(self):
|
||||||
band = Band.objects.create(name="Bogey Blues")
|
band = Band.objects.create(name="Bogey Blues")
|
||||||
pk = band.pk
|
pk = band.pk
|
||||||
@ -335,6 +338,7 @@ class AdminForeignKeyRawIdWidget(TestDataMixin, TestCase):
|
|||||||
"Select a valid choice. That choice is not one of the available choices.",
|
"Select a valid choice. That choice is not one of the available choices.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_invalid_target_id(self):
|
def test_invalid_target_id(self):
|
||||||
for test_str in ("Iñtërnâtiônàlizætiøn", "1234'", -1234):
|
for test_str in ("Iñtërnâtiônàlizætiøn", "1234'", -1234):
|
||||||
# This should result in an error message, not a server exception.
|
# This should result in an error message, not a server exception.
|
||||||
@ -1610,6 +1614,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase):
|
|||||||
self.assertCountSeleniumElements("#id_students_to > option", 2)
|
self.assertCountSeleniumElements("#id_students_to > option", 2)
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
class AdminRawIdWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
|
class AdminRawIdWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
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
|
from django.test import SimpleTestCase, ignore_warnings
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
|
|
||||||
from . import FormFieldAssertionsMixin
|
from . import FormFieldAssertionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
||||||
def test_urlfield_widget(self):
|
def test_urlfield_widget(self):
|
||||||
f = URLField()
|
f = URLField()
|
||||||
@ -26,7 +28,9 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
|||||||
f.clean("http://abcdefghijklmnopqrstuvwxyz.com")
|
f.clean("http://abcdefghijklmnopqrstuvwxyz.com")
|
||||||
|
|
||||||
def test_urlfield_clean(self):
|
def test_urlfield_clean(self):
|
||||||
f = URLField(required=False)
|
# RemovedInDjango60Warning: When the deprecation ends, remove the
|
||||||
|
# assume_scheme argument.
|
||||||
|
f = URLField(required=False, assume_scheme="https")
|
||||||
tests = [
|
tests = [
|
||||||
("http://localhost", "http://localhost"),
|
("http://localhost", "http://localhost"),
|
||||||
("http://example.com", "http://example.com"),
|
("http://example.com", "http://example.com"),
|
||||||
@ -38,8 +42,8 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
|||||||
"http://example.com?some_param=some_value",
|
"http://example.com?some_param=some_value",
|
||||||
"http://example.com?some_param=some_value",
|
"http://example.com?some_param=some_value",
|
||||||
),
|
),
|
||||||
("valid-with-hyphens.com", "http://valid-with-hyphens.com"),
|
("valid-with-hyphens.com", "https://valid-with-hyphens.com"),
|
||||||
("subdomain.domain.com", "http://subdomain.domain.com"),
|
("subdomain.domain.com", "https://subdomain.domain.com"),
|
||||||
("http://200.8.9.10", "http://200.8.9.10"),
|
("http://200.8.9.10", "http://200.8.9.10"),
|
||||||
("http://200.8.9.10:8000/test", "http://200.8.9.10:8000/test"),
|
("http://200.8.9.10:8000/test", "http://200.8.9.10:8000/test"),
|
||||||
("http://valid-----hyphens.com", "http://valid-----hyphens.com"),
|
("http://valid-----hyphens.com", "http://valid-----hyphens.com"),
|
||||||
@ -49,7 +53,7 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"www.example.com/s/http://code.djangoproject.com/ticket/13804",
|
"www.example.com/s/http://code.djangoproject.com/ticket/13804",
|
||||||
"http://www.example.com/s/http://code.djangoproject.com/ticket/13804",
|
"https://www.example.com/s/http://code.djangoproject.com/ticket/13804",
|
||||||
),
|
),
|
||||||
# Normalization.
|
# Normalization.
|
||||||
("http://example.com/ ", "http://example.com/"),
|
("http://example.com/ ", "http://example.com/"),
|
||||||
@ -135,3 +139,24 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
|
|||||||
msg = "__init__() got multiple values for keyword argument 'strip'"
|
msg = "__init__() got multiple values for keyword argument 'strip'"
|
||||||
with self.assertRaisesMessage(TypeError, msg):
|
with self.assertRaisesMessage(TypeError, msg):
|
||||||
URLField(strip=False)
|
URLField(strip=False)
|
||||||
|
|
||||||
|
def test_urlfield_assume_scheme(self):
|
||||||
|
f = URLField()
|
||||||
|
# RemovedInDjango60Warning: When the deprecation ends, replace with:
|
||||||
|
# "https://example.com"
|
||||||
|
self.assertEqual(f.clean("example.com"), "http://example.com")
|
||||||
|
f = URLField(assume_scheme="http")
|
||||||
|
self.assertEqual(f.clean("example.com"), "http://example.com")
|
||||||
|
f = URLField(assume_scheme="https")
|
||||||
|
self.assertEqual(f.clean("example.com"), "https://example.com")
|
||||||
|
|
||||||
|
|
||||||
|
class URLFieldAssumeSchemeDeprecationTest(FormFieldAssertionsMixin, SimpleTestCase):
|
||||||
|
def test_urlfield_raises_warning(self):
|
||||||
|
msg = (
|
||||||
|
"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."
|
||||||
|
)
|
||||||
|
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
||||||
|
f = URLField()
|
||||||
|
self.assertEqual(f.clean("example.com"), "http://example.com")
|
||||||
|
@ -23,7 +23,8 @@ from django.forms import (
|
|||||||
utils,
|
utils,
|
||||||
)
|
)
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.test import SimpleTestCase, TestCase
|
from django.test import SimpleTestCase, TestCase, ignore_warnings
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
from ..models import ChoiceModel
|
from ..models import ChoiceModel
|
||||||
@ -167,7 +168,8 @@ class FormsErrorMessagesTestCase(SimpleTestCase, AssertFormErrorsMixin):
|
|||||||
"invalid": "INVALID",
|
"invalid": "INVALID",
|
||||||
"max_length": '"%(value)s" has more than %(limit_value)d characters.',
|
"max_length": '"%(value)s" has more than %(limit_value)d characters.',
|
||||||
}
|
}
|
||||||
f = URLField(error_messages=e, max_length=17)
|
with ignore_warnings(category=RemovedInDjango60Warning):
|
||||||
|
f = URLField(error_messages=e, max_length=17)
|
||||||
self.assertFormErrors(["REQUIRED"], f.clean, "")
|
self.assertFormErrors(["REQUIRED"], f.clean, "")
|
||||||
self.assertFormErrors(["INVALID"], f.clean, "abc.c")
|
self.assertFormErrors(["INVALID"], f.clean, "abc.c")
|
||||||
self.assertFormErrors(
|
self.assertFormErrors(
|
||||||
|
@ -5,8 +5,15 @@ from django.contrib.contenttypes.admin import GenericTabularInline
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.forms.formsets import DEFAULT_MAX_NUM
|
from django.forms.formsets import DEFAULT_MAX_NUM
|
||||||
from django.forms.models import ModelForm
|
from django.forms.models import ModelForm
|
||||||
from django.test import RequestFactory, SimpleTestCase, TestCase, override_settings
|
from django.test import (
|
||||||
|
RequestFactory,
|
||||||
|
SimpleTestCase,
|
||||||
|
TestCase,
|
||||||
|
ignore_warnings,
|
||||||
|
override_settings,
|
||||||
|
)
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
|
|
||||||
from .admin import MediaInline, MediaPermanentInline
|
from .admin import MediaInline, MediaPermanentInline
|
||||||
from .admin import site as admin_site
|
from .admin import site as admin_site
|
||||||
@ -21,6 +28,7 @@ class TestDataMixin:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
||||||
class GenericAdminViewTest(TestDataMixin, TestCase):
|
class GenericAdminViewTest(TestDataMixin, TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -95,6 +103,7 @@ class GenericAdminViewTest(TestDataMixin, TestCase):
|
|||||||
self.assertEqual(response.status_code, 302) # redirect somewhere
|
self.assertEqual(response.status_code, 302) # redirect somewhere
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
||||||
class GenericInlineAdminParametersTest(TestDataMixin, TestCase):
|
class GenericInlineAdminParametersTest(TestDataMixin, TestCase):
|
||||||
factory = RequestFactory()
|
factory = RequestFactory()
|
||||||
@ -296,6 +305,7 @@ class GenericInlineAdminWithUniqueTogetherTest(TestDataMixin, TestCase):
|
|||||||
|
|
||||||
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
@override_settings(ROOT_URLCONF="generic_inline_admin.urls")
|
||||||
class NoInlineDeletionTest(SimpleTestCase):
|
class NoInlineDeletionTest(SimpleTestCase):
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_no_deletion(self):
|
def test_no_deletion(self):
|
||||||
inline = MediaPermanentInline(EpisodePermanent, admin_site)
|
inline = MediaPermanentInline(EpisodePermanent, admin_site)
|
||||||
fake_request = object()
|
fake_request = object()
|
||||||
@ -321,6 +331,7 @@ class GenericInlineModelAdminTest(SimpleTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.site = AdminSite()
|
self.site = AdminSite()
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_get_formset_kwargs(self):
|
def test_get_formset_kwargs(self):
|
||||||
media_inline = MediaInline(Media, AdminSite())
|
media_inline = MediaInline(Media, AdminSite())
|
||||||
|
|
||||||
@ -360,6 +371,7 @@ class GenericInlineModelAdminTest(SimpleTestCase):
|
|||||||
["keywords", "id", "DELETE"],
|
["keywords", "id", "DELETE"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_custom_form_meta_exclude(self):
|
def test_custom_form_meta_exclude(self):
|
||||||
"""
|
"""
|
||||||
The custom ModelForm's `Meta.exclude` is respected by
|
The custom ModelForm's `Meta.exclude` is respected by
|
||||||
@ -403,6 +415,7 @@ class GenericInlineModelAdminTest(SimpleTestCase):
|
|||||||
["description", "keywords", "id", "DELETE"],
|
["description", "keywords", "id", "DELETE"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_get_fieldsets(self):
|
def test_get_fieldsets(self):
|
||||||
# get_fieldsets is called when figuring out form fields.
|
# get_fieldsets is called when figuring out form fields.
|
||||||
# Refs #18681.
|
# Refs #18681.
|
||||||
|
@ -21,8 +21,9 @@ from django.forms.models import (
|
|||||||
modelform_factory,
|
modelform_factory,
|
||||||
)
|
)
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
|
from django.test import SimpleTestCase, TestCase, ignore_warnings, skipUnlessDBFeature
|
||||||
from django.test.utils import isolate_apps
|
from django.test.utils import isolate_apps
|
||||||
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Article,
|
Article,
|
||||||
@ -369,6 +370,7 @@ class ModelFormBaseTest(TestCase):
|
|||||||
obj = form.save()
|
obj = form.save()
|
||||||
self.assertEqual(obj.name, "")
|
self.assertEqual(obj.name, "")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_save_blank_null_unique_charfield_saves_null(self):
|
def test_save_blank_null_unique_charfield_saves_null(self):
|
||||||
form_class = modelform_factory(
|
form_class = modelform_factory(
|
||||||
model=NullableUniqueCharFieldModel, fields="__all__"
|
model=NullableUniqueCharFieldModel, fields="__all__"
|
||||||
@ -907,6 +909,13 @@ class ModelFormBaseTest(TestCase):
|
|||||||
self.assertEqual(m2.date_published, datetime.date(2010, 1, 1))
|
self.assertEqual(m2.date_published, datetime.date(2010, 1, 1))
|
||||||
|
|
||||||
|
|
||||||
|
# RemovedInDjango60Warning.
|
||||||
|
# It's a temporary workaround for the deprecation period.
|
||||||
|
class HttpsURLField(forms.URLField):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(assume_scheme="https", **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class FieldOverridesByFormMetaForm(forms.ModelForm):
|
class FieldOverridesByFormMetaForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
@ -930,7 +939,7 @@ class FieldOverridesByFormMetaForm(forms.ModelForm):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
field_classes = {
|
field_classes = {
|
||||||
"url": forms.URLField,
|
"url": HttpsURLField,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2857,6 +2866,7 @@ class ModelOtherFieldTests(SimpleTestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango60Warning)
|
||||||
def test_url_on_modelform(self):
|
def test_url_on_modelform(self):
|
||||||
"Check basic URL field validation on model forms"
|
"Check basic URL field validation on model forms"
|
||||||
|
|
||||||
@ -2881,6 +2891,19 @@ class ModelOtherFieldTests(SimpleTestCase):
|
|||||||
)
|
)
|
||||||
self.assertTrue(HomepageForm({"url": "http://example.com/foo/bar"}).is_valid())
|
self.assertTrue(HomepageForm({"url": "http://example.com/foo/bar"}).is_valid())
|
||||||
|
|
||||||
|
def test_url_modelform_assume_scheme_warning(self):
|
||||||
|
msg = (
|
||||||
|
"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."
|
||||||
|
)
|
||||||
|
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
||||||
|
|
||||||
|
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
|
||||||
@ -2900,23 +2923,27 @@ class ModelOtherFieldTests(SimpleTestCase):
|
|||||||
model = Article
|
model = Article
|
||||||
fields = ("headline", "created")
|
fields = ("headline", "created")
|
||||||
|
|
||||||
def test_http_prefixing(self):
|
def test_https_prefixing(self):
|
||||||
"""
|
"""
|
||||||
If the http:// prefix is omitted on form input, the field adds it again.
|
If the https:// prefix is omitted on form input, the field adds it
|
||||||
|
again.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class HomepageForm(forms.ModelForm):
|
class HomepageForm(forms.ModelForm):
|
||||||
|
# RemovedInDjango60Warning.
|
||||||
|
url = forms.URLField(assume_scheme="https")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Homepage
|
model = Homepage
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
form = HomepageForm({"url": "example.com"})
|
form = HomepageForm({"url": "example.com"})
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
self.assertEqual(form.cleaned_data["url"], "http://example.com")
|
self.assertEqual(form.cleaned_data["url"], "https://example.com")
|
||||||
|
|
||||||
form = HomepageForm({"url": "example.com/test"})
|
form = HomepageForm({"url": "example.com/test"})
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
self.assertEqual(form.cleaned_data["url"], "http://example.com/test")
|
self.assertEqual(form.cleaned_data["url"], "https://example.com/test")
|
||||||
|
|
||||||
|
|
||||||
class OtherModelFormTests(TestCase):
|
class OtherModelFormTests(TestCase):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user