3

I've been banging my head against the wall trying to figure out why I can't pass a JSON string generated from a Django Model into a template's javascript static file. As it turns out, the problem wasn't at the Model level (using serializers.serialize) - putting an identical string in the script itself will successfully parse, but passing the string in 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 fails with JSON.parse: expected property name or '}' at line 1 column 2 of the JSON data:

var json_data = load_texas();

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

but is successful if the same string is just entered in the script:

// 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 something about the way Django handles context variables?

Edit:

Not quite a fix for passing a string, but I'm now passing a JSON object directly to the template which solves my original problem of getting Models into javascript.

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})
2
  • Have you checked how the html looks after loading (e.g. with the Chrome developer tools etc.)? Could there be double quotes around the json string? Commented Jul 11, 2017 at 4:06
  • @ger.s.brett The text appears in the html without quotes. Commented Jul 11, 2017 at 18:07

1 Answer 1

3

You need to disable autoescaping.

return '{{ tx|safe }}';

Note, you really should not create JSON data as strings in your view; create it as a Python datastructure, then use json.dumps().

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

3 Comments

I forgot about using safe, but it didn't seem to make a difference when passing a string. You can see in my edited question I started passing my Models as a JSON object using json.loads() (because the Django serializer module spits out a string representation), which works, but are there better Django practices than this?
No that doesn't make sense. Why do you want to convert the JSON back into Python data structures before passing to the template?
You're right, that doesn't make sense. It was working for the simple example above (how?) but now I'm getting ReferenceError: None is not defined.

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.