diff --git a/django/utils/html.py b/django/utils/html.py index c32a36fa93..56d65a8d21 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -3,9 +3,11 @@ import html import json import re +import warnings from html.parser import HTMLParser from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit +from django.utils.deprecation import RemovedInDjango60Warning from django.utils.encoding import punycode from django.utils.functional import Promise, keep_lazy, keep_lazy_text from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS @@ -100,6 +102,13 @@ def format_html(format_string, *args, **kwargs): and call mark_safe() on the result. This function should be used instead of str.format or % interpolation to build up small HTML fragments. """ + if not (args or kwargs): + # RemovedInDjango60Warning: when the deprecation ends, replace with: + # raise ValueError("args or kwargs must be provided.") + warnings.warn( + "Calling format_html() without passing args or kwargs is deprecated.", + RemovedInDjango60Warning, + ) args_safe = map(conditional_escape, args) kwargs_safe = {k: conditional_escape(v) for (k, v) in kwargs.items()} return mark_safe(format_string.format(*args_safe, **kwargs_safe)) diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index b27348adb0..fa2a1c0a0c 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -35,6 +35,9 @@ details on these changes. * The default scheme for ``forms.URLField`` will change from ``"http"`` to ``"https"``. +* Support for calling ``format_html()`` without passing args or kwargs will be + removed. + .. _deprecation-removed-in-5.1: 5.1 diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index e37e59ddf2..acbe5d51a6 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -651,6 +651,11 @@ escaping HTML. through :func:`conditional_escape` which (ultimately) calls :func:`~django.utils.encoding.force_str` on the values. + .. deprecated:: 5.0 + + Support for calling ``format_html()`` without passing args or kwargs is + deprecated. + .. function:: format_html_join(sep, format_string, args_generator) A wrapper of :func:`format_html`, for the common case of a group of diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index 38b49986c5..98bd5d2a9f 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -454,6 +454,9 @@ Miscellaneous * The default scheme for ``forms.URLField`` will change from ``"http"`` to ``"https"`` in Django 6.0. +* Support for calling ``format_html()`` without passing args or kwargs will be + removed. + Features removed in 5.0 ======================= diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py index b7a7396075..ad31b8cc5b 100644 --- a/tests/utils_tests/test_html.py +++ b/tests/utils_tests/test_html.py @@ -3,6 +3,7 @@ from datetime import datetime from django.core.serializers.json import DjangoJSONEncoder from django.test import SimpleTestCase +from django.utils.deprecation import RemovedInDjango60Warning from django.utils.functional import lazystr from django.utils.html import ( conditional_escape, @@ -65,6 +66,15 @@ class TestUtilsHtml(SimpleTestCase): "< Dangerous > safe < dangerous again safe again", ) + def test_format_html_no_params(self): + msg = "Calling format_html() without passing args or kwargs is deprecated." + # RemovedInDjango60Warning: when the deprecation ends, replace with: + # msg = "args or kwargs must be provided." + # with self.assertRaisesMessage(ValueError, msg): + with self.assertWarnsMessage(RemovedInDjango60Warning, msg): + name = "Adam" + self.assertEqual(format_html(f"{name}"), "Adam") + def test_linebreaks(self): items = ( ("para1\n\npara2\r\rpara3", "
para1
\n\npara2
\n\npara3
"),