[Django]-Unicode string display on Django template

7👍

bar = json.dumps(foo, ensure_ascii=False) will result in bar being a unicode object; without ensure_ascii=False, bar is a str.

Django’s smart_text method might also be useful for conversions.

4👍

<div id="foobar">{{ foobar }}</div>

will display the unicode string as byte string: { "name":"\u8d5e\u4e00\u4e0b\u6211\u4eec" }

This is displaying the whole object in its JSON-encoded form. Whilst you could use json.dumps(..., ensure_ascii=False) to keep non-ASCII characters like the Chinese in their raw form rather than encoded into ASCII-safe-JSON, this would still give you {"name": "赞一下我们"} which is probably not what you want.

If you only want the name property of the object included in the div, you will need to pass the item foo['name'] to your template – or the whole of foo and have the template include {{foo.name}} – rather than including the whole encoded JSON object from foobar.

foobar=JSON.encode('{{foobar|safe}}'); 

There is no method encode on the ECMA standard JSON object, so I don’t know what that’s doing.

The JSON-encoding method is JSON.stringify. But you don’t want to encode here – you already have a string with a JSON representation of an object here because you encoded it above at the server side in the call to json.dumps. Probably you meant:

var foobar = JSON.parse('{{foobar|safe}}'); 

which would work for your particular value of name, but not necessarily in general. For example if the name was a\nb then you would get:

JSON.parse('{"name": "a\nb"}')

in which case the \n would get parsed by the JavaScript interpreter as being a newline character in the string, and so the string parsed as JSON would be:

{"name": "a
b"}

which is a syntax error. There are also security issues here – contrary to the |safe assertion, this is not safe. If the name property contained the string </script then you would end up with a prematurely-ended script element, which can lead to cross-site scripting attacks:

<script>
var foobar = JSON.parse('</script>
<script>alert();//attacker code here');</script>

You could attempt to get around these by doing a second layer of JS string literal encoding on the JSON at the server side, and manually replace < with \u003C. But probably it’s best to take a different approach – generating executable code on the fly is fraught with problems in general, especially when you have multiple different syntaxes in the mix (Python/Django-template, HTML and JS/JSON).

If you write data to the document (for example in a data- attribute) rather than the script then you can keep the normal and safe template behaviour of HTML-escaping. Then the JS side can read the data out of the DOM. For example:

<div id="foobar" data-foobar="{{ foobar }}">
...

var foobar = $('#foobar').data('foobar');

(jQuery’s data method implicitly does the JSON.parse for you.)

This helps with separation of concerns, getting JS out into external scripts, and potentially eventually using Content-Security-Policy.

1👍

You need to reference the element within the dict, without JSON-encoding it.

return render_to_response(..., {..., 'foo': foo}, ...)

{{ foo.name }}

Leave a comment