Browse Source

Fixed #33302 -- Made element_id optional argument for json_script template filter.

Added versionchanged note in documentation
Baptiste Mispelon 3 years ago
parent
commit
e6e664a711

+ 2 - 2
django/template/defaultfilters.py

@@ -83,10 +83,10 @@ def escapejs_filter(value):
 
 
 @register.filter(is_safe=True)
-def json_script(value, element_id):
+def json_script(value, element_id=None):
     """
     Output value JSON-encoded, wrapped in a <script type="application/json">
-    tag.
+    tag (with an optional id).
     """
     return _json_script(value, element_id)
 

+ 8 - 5
django/utils/html.py

@@ -61,7 +61,7 @@ _json_script_escapes = {
 }
 
 
-def json_script(value, element_id):
+def json_script(value, element_id=None):
     """
     Escape all the HTML/XML special characters with their unicode escapes, so
     value is safe to be output anywhere except for inside a tag attribute. Wrap
@@ -69,10 +69,13 @@ def json_script(value, element_id):
     """
     from django.core.serializers.json import DjangoJSONEncoder
     json_str = json.dumps(value, cls=DjangoJSONEncoder).translate(_json_script_escapes)
-    return format_html(
-        '<script id="{}" type="application/json">{}</script>',
-        element_id, mark_safe(json_str)
-    )
+    if element_id:
+        template = '<script id="{}" type="application/json">{}</script>'
+        args = (element_id, mark_safe(json_str))
+    else:
+        template = '<script type="application/json">{}</script>'
+        args = (mark_safe(json_str),)
+    return format_html(template, *args)
 
 
 def conditional_escape(text):

+ 5 - 1
docs/ref/templates/builtins.txt

@@ -1832,7 +1832,7 @@ If ``value`` is the list ``['a', 'b', 'c']``, the output will be the string
 Safely outputs a Python object as JSON, wrapped in a ``<script>`` tag, ready
 for use with JavaScript.
 
-**Argument:** HTML "id" of the ``<script>`` tag.
+**Argument:** The optional HTML "id" of the ``<script>`` tag.
 
 For example::
 
@@ -1861,6 +1861,10 @@ This is compatible with a strict Content Security Policy that prohibits in-page
 script execution. It also maintains a clean separation between passive data and
 executable code.
 
+.. versionchanged:: 4.1
+
+    In older versions, the HTML "id" was a required argument.
+
 .. templatefilter:: last
 
 ``last``

+ 2 - 1
docs/releases/4.1.txt

@@ -210,7 +210,8 @@ Signals
 Templates
 ~~~~~~~~~
 
-* ...
+* :tfilter:`json_script` template filter now allows wrapping in a ``<script>``
+  tag without the HTML ``id`` attribute.
 
 Tests
 ~~~~~

+ 5 - 0
tests/template_tests/filter_tests/test_json_script.py

@@ -17,3 +17,8 @@ class JsonScriptTests(SimpleTestCase):
             '{"a": "testing\\r\\njson \'string\\" \\u003Cb\\u003Eescaping\\u003C/b\\u003E"}'
             '</script>'
         )
+
+    @setup({'json-tag02': '{{ value|json_script }}'})
+    def test_without_id(self):
+        output = self.engine.render_to_string('json-tag02', {'value': {}})
+        self.assertEqual(output, '<script type="application/json">{}</script>')

+ 6 - 0
tests/utils_tests/test_html.py

@@ -173,6 +173,12 @@ class TestUtilsHtml(SimpleTestCase):
             with self.subTest(arg=arg):
                 self.assertEqual(json_script(arg, 'test_id'), expected)
 
+    def test_json_script_without_id(self):
+        self.assertHTMLEqual(
+            json_script({'key': 'value'}),
+            '<script type="application/json">{"key": "value"}</script>',
+        )
+
     def test_smart_urlquote(self):
         items = (
             ('http://öäü.com/', 'http://xn--4ca9at.com/'),