0

I am passing a python list to a django template like this:

in views.py:

dat = [-77.448599999999999, 37.536900000000003, u'Virginia War Memorial', 1.0]
result={"dat":dat}
return render(request,'result_map.html', {'form': form,'result':result})

and in my template:

var dat = {{ result.dat }}

but in the rendered html I get:

var dat = [-77.448599999999999, 37.536900000000003, u'Virginia War Memorial', 1.0]

which gives an error.

How can I get:

var dat = [-77.448599999999999, 37.536900000000003, 'Virginia War Memorial', 1.0]

thanks

5
  • Are you seeing this output in a browser? Commented Feb 14, 2016 at 16:50
  • nope. the script just quits. I print the html after I render it Commented Feb 14, 2016 at 16:51
  • 2
    If you render the whole list like that, it will output the str of the list. If you want proper output for each element, you should probably access them directly: '{{ result.dat.2 }}' Commented Feb 14, 2016 at 16:55
  • Assuming that you are bothered by the extraneous u. The ' will be properly displayed as ' by a browser. Commented Feb 14, 2016 at 16:58
  • You're first answer was correct and very helpful. I suggest you write it as a real answer. thanks Commented Feb 14, 2016 at 17:05

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.