19

I have a variable that contains JSON I need to pass into a template. I'm defining it as a variable and then passing it into the template successfully. However, I need the format to replace the quotes with ", but is replacing with '. This is causing issues with the service that I"m passing this to.

image_upload_params = 
{
  "auth": {
    "key": "xxx"
  },
  "template_id": "xxx",
  "redirect_url": "url-here",
}

Here is how it's coming up in the template:

{'redirect_url': 'url-here', 'template_id': 'xxx', 'auth': {'key': 'xxx'}}

Any idea how to get it to use " instead?

Brenden
  • 8,264
  • 14
  • 48
  • 78

4 Answers4

37

Django 2.1 added the json_script template filter:

Safely outputs a Python object as JSON, wrapped in a tag, ready for use with JavaScript

Insert this in your template:

{{ value|json_script:"hello-data" }}

It renders to:

<script id="hello-data" type="application/json">{"hello": "world"}</script>

Then, you can safely load this object in a JavaScript variable:

var value = JSON.parse(document.getElementById('hello-data').textContent);

This approach is safer than simply writing var value = {{value|safe}}; because it protects you from XSS attacks (more in this ticket).

Benoit Blanchon
  • 13,364
  • 4
  • 73
  • 81
  • 1
    a simpler way: ```{{ value|json_script:"hello_data" }}``` and access by ```var value = JSON.parse(hello_data.textContent);``` – anandogc Sep 21 '22 at 10:19
  • 1
    @anandogc, it works, but it is considered a bad practice. See https://stackoverflow.com/q/3434278/1164966, for example. – Benoit Blanchon Sep 22 '22 at 07:58
21

Use SafeString:

from django.utils.safestring import SafeString

def view(request):
    ...
    return render(request, 'template.html', {'upload_params': SafeString(json_string)})
Matthew Hegarty
  • 3,791
  • 2
  • 27
  • 42
Zach Kelling
  • 52,505
  • 13
  • 109
  • 108
  • Thanks. I'm realizing the main issue. When I am setting the variable, python is changing my double quotes to single quotes. That's the root of the problem. For this service, I need for them to be double quotes. Ideas? – Brenden Jun 08 '11 at 23:10
  • I'm perplexed why that would matter...if you use the `json` module it will safely escape everything for you. If you want to though, you can save the JSON as a string in the format you want, just mark it with `SafeString` and pass to the template. – Zach Kelling Jun 08 '11 at 23:19
1

I found a method which uses a django custom template filter.

The filter code looks like this

custom_filter.py

from django.template import Library
from django.utils.safestring import SafeString
import json

register = Library()


@register.filter("escapedict")
def escapedict(data):
    if not isinstance(data, dict):
        return data
    for key in data:
        if isinstance(data[key], int) and not isinstance(data[key], bool):
            data[key] = int(SafeString(data[key]))
        else:
            data[key] = SafeString(data[key])
    return json.dumps(data)

django document

And in the template, we use the filter like this:

...
{% load custom_filter %}
some html
...
onclick="jsfunc('{{data|escapedict}}')" 
...
some html
...
...
function showdetails(data){
    parse data here
}
...
...
Su Kai
  • 21
  • 4
0

As zeekay mentioned, just use the python built-in json library. It will automatically output valid json data. You'll still have to mark it "safe" for django to use in templates but you can do that using the "safe" template filter.

Exelian
  • 5,749
  • 1
  • 30
  • 49