Javascript – Pass a JSON string to a Django template

Pass a JSON string to a Django template… here is a solution to the problem.

Pass a JSON string to a Django template

I’ve been banging my head against the wall trying to figure out why I can’t pass the JSON string generated by the Django model into the template’s javascript static file. It turns out that the problem is not at the model level (using serializers.serialize) – putting the same string into the script itself will parse successfully, but passing the string will not:

views.py:

def texas(request):
    test_json = '{"incidents": [{"field1": 1, "field2": 2}], "debug": 1}'
    return render(request, 'tx/texas.html', {'tx': test_json})

tx/texas.html:

{% load staticfiles %}

<html>
    <head>
      <title>texas map</title>
    </head>
    <body>
        <p id='texas'></p>
        <script>
            function load_texas() {
                return '{{ tx }}';
            }
        </script>
        <script src="{% static 'js/texas.js' %}"></script>
    </body>
</html>

js/texas.js failed with JSON.parse: JSON data row 1, column 2 expected property name or “}”:

var json_data = load_texas();

var paragraph = document.getElementById('texas');
try {
    paragraph.innerHTML = JSON.parse(json_data);
}
catch(err) {
    paragraph.innerHTML = err.message;
}

But if you enter the same string in the script, it succeeds:

// this JSON string is identical to the one passed in views.py
var json_data = '{"incidents": [{"field1": 1, "field2": 2}], "debug": 1}';

Am I missing the way Django handles context variables?

Edit:

Not a good fix for passing strings, but I’m now passing a JSON object directly to the template, which solved my problem with importing the model into javascript initially.

views.py:

from django.shortcuts import render
from django.core import serializers
import json
from .models import Tx

def texas(request):
    tx_database = Tx.objects.all()

# Django serialize puts square brackets around the string,
    # so slice them off.
    json_string = serializers.serialize('json', tx_database)[1:-1]

# Load string into JSON object... is this best practice?
    test_json = json.loads(json_string)
    return render(request, 'tx/texas.html', {'tx': test_json})

Solution

You need to disable auto-escaping.

return '{{ tx|safe }}';

Note that you really shouldn’t create JSON data as strings in View; Create it as a Python data structure and use json.dumps().

Related Problems and Solutions