diff options
| author | nabil-rady <midorady9999@gmail.com> | 2024-08-14 00:58:37 +0300 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-08-20 08:20:34 +0200 |
| commit | 231c0d85931b5afde3e3caec0e6bc5ca6132bb7a (patch) | |
| tree | 8f7fbb7deb54c15507852eec31740f2a1a7adfbf | |
| parent | ca1318988c68f623ab12ab4ddb04eabb8afe5a33 (diff) | |
Fixed #35668 -- Added mapping support to format_html_join.
| -rw-r--r-- | django/utils/html.py | 8 | ||||
| -rw-r--r-- | docs/ref/utils.txt | 25 | ||||
| -rw-r--r-- | docs/releases/5.2.txt | 4 | ||||
| -rw-r--r-- | tests/utils_tests/test_html.py | 21 |
4 files changed, 54 insertions, 4 deletions
diff --git a/django/utils/html.py b/django/utils/html.py index 154c820d34..3ad920aca0 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -4,6 +4,7 @@ import html import json import re import warnings +from collections.abc import Mapping from html.parser import HTMLParser from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit @@ -155,7 +156,12 @@ def format_html_join(sep, format_string, args_generator): """ return mark_safe( conditional_escape(sep).join( - format_html(format_string, *args) for args in args_generator + ( + format_html(format_string, **args) + if isinstance(args, Mapping) + else format_html(format_string, *args) + ) + for args in args_generator ) ) diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index d6c70a9bb0..33e0fceadf 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -699,10 +699,29 @@ escaping HTML. joined using ``sep``. ``sep`` is also passed through :func:`conditional_escape`. - ``args_generator`` should be an iterator that returns the sequence of - ``args`` that will be passed to :func:`format_html`. For example:: + ``args_generator`` should be an iterator that yields arguments to pass to + :func:`format_html`, either sequences of positional arguments or mappings of + keyword arguments. - format_html_join("\n", "<li>{} {}</li>", ((u.first_name, u.last_name) for u in users)) + For example, tuples can be used for positional arguments:: + + format_html_join( + "\n", + "<li>{} {}</li>", + ((u.first_name, u.last_name) for u in users), + ) + + Or dictionaries can be used for keyword arguments:: + + format_html_join( + "\n", + '<li data-id="{id}">{id} {title}</li>', + ({"id": b.id, "title": b.title} for b in books), + ) + + .. versionchanged:: 5.2 + + Support for mappings in ``args_generator`` was added. .. function:: json_script(value, element_id=None, encoder=None) diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index fa25737432..0caeef01cf 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -267,6 +267,10 @@ Utilities values. This aligns with the :py:class:`str` addition behavior and allows ``__radd__`` to be used if available. +* :func:`~django.utils.html.format_html_join` now supports taking an iterable + of mappings, passing their contents as keyword arguments to + :func:`~django.utils.html.format_html`. + Validators ~~~~~~~~~~ diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py index 82dbd58f12..f6373e3048 100644 --- a/tests/utils_tests/test_html.py +++ b/tests/utils_tests/test_html.py @@ -10,6 +10,7 @@ from django.utils.html import ( escape, escapejs, format_html, + format_html_join, html_safe, json_script, linebreaks, @@ -75,6 +76,26 @@ class TestUtilsHtml(SimpleTestCase): name = "Adam" self.assertEqual(format_html(f"<i>{name}</i>"), "<i>Adam</i>") + def test_format_html_join_with_positional_arguments(self): + self.assertEqual( + format_html_join( + "\n", + "<li>{}) {}</li>", + [(1, "Emma"), (2, "Matilda")], + ), + "<li>1) Emma</li>\n<li>2) Matilda</li>", + ) + + def test_format_html_join_with_keyword_arguments(self): + self.assertEqual( + format_html_join( + "\n", + "<li>{id}) {text}</li>", + [{"id": 1, "text": "Emma"}, {"id": 2, "text": "Matilda"}], + ), + "<li>1) Emma</li>\n<li>2) Matilda</li>", + ) + def test_linebreaks(self): items = ( ("para1\n\npara2\r\rpara3", "<p>para1</p>\n\n<p>para2</p>\n\n<p>para3</p>"), |
