[Fixed]-Django template error while rendering a unicode string

1👍

I think you need to pass it through the safe filter if you want the raw string:
{{ result.dat|safe }}

You can also use the {% autoescape off %} block if you want to affect a larger block of the template.

0👍

var dat = {{ result.dat }}

You’re trying to inject into JavaScript, presumably in a <script> block. You need output that is formatted in JavaScript syntax, but you’re implicitly converting a Python list to a string, which will give a Python-syntax list literal, not a JavaScript one. There are a number of differences, including text (Unicode) strings in the list being prefixed with u in Python 2 but not JS.

You’re also using the default autoescaping for Django templates, which is HTML-escaping. That would be right for injecting into HTML content, but you’re injecting into JavaScript, so you get wrong escapes like &#39; for '. You can prevent this by adding the |safe filter to avoid the HTML-escaping, but then you have no escaping at all, so your page will be vulnerable to script injection (cross-site scripting).

The right way to output a structured value into a <script> block is:

  • json.dumps to turn it into a JSON string
  • replace any instances of the character < in the string with the JSON string literal escape \u003C, so that the string </script> can’t be used to escape from the <script> block and inject HTML
  • mark as safe.

You can combine these operations into a custom filter. Unfortunately Django itself doesn’t ship one.

A better approach is to avoid injecting into JavaScript at all. Instead write the json.dumps output into the HTML document using the standard escaping and read it from there using DOM:

return render(request, 'result_map.html', {'form': form, 'dat': json.dumps(dat)})
...
<body data-dat="{{ dat }}">
...
var dat= JSON.parse(document.body.getAttribute('data-dat'));

this allows you to keep your JS completely out of your HTML pages, which would also allow you to use more secure Content-Security-Policy settings.

Leave a comment