15

In views.py, I have time series data stored in a dictionary as follows:

time_series = {"timestamp1": occurrences, "timestamp2": occurrences}

where each timestamp is in unix time and occurrences is an integer.

Is there a way to pass the time series data as a json object in the context of the render function?

Why do this: I am using Cal-heatmap on the front end which requires the data to be in json format. Ajax requests work just fine for now but I ideally would like to use the render approach if possible.

jkarimi
  • 1,247
  • 2
  • 15
  • 27
  • Update from 2021 with simple, built-in solution: https://stackoverflow.com/a/66658209/4671300 – talz Mar 16 '21 at 15:25

4 Answers4

51

If a frontend library needs a to parse JSON, you can use the json library to convert a python dict to a JSON valid string. Use the escapejs filter

import json

def foo(request):
    json_string = json.dumps(<time_series>)
    render(request, "foo.html", {'time_series_json_string': json_string})


<script>
    var jsonObject = JSON.parse('{{ time_series_json_string | escapejs }}');
</script>
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • 1
    How about `var jsonObject = {{ time_series_json_string }};`? If you know **for sure** your data cannot contain unicode escapes or the ` – spectras Jul 01 '15 at 02:30
  • @spectras indeed, good point in the context of this particular question. Just in case this post gets interpreted for a different payload I guess :P – Yuji 'Tomita' Tomita Jul 01 '15 at 02:55
  • @Yuji'Tomita'Tomita this works great! is there any reason to pick this approach over an ajax request approach or vice versa, in general? – jkarimi Jul 01 '15 at 02:55
  • @JayKarimi only because this question specifically asked for the `render` approach. The reasons not to use ajax would be: apparently this is not necessarily dynamic content. Why add AJAX JS / callbacks, ajax view + template render, if not necessary. If anything AJAX should cause slower rendering *and* additional complexity for a 2 key object. Or maybe not: the page could be more easily full page cached while the AJAX is cached more frequently. All depends! – Yuji 'Tomita' Tomita Jul 01 '15 at 02:58
  • Is this method safe if your json has user submitted content? – cammil Aug 07 '21 at 23:04
7

Pass a json.dumps value to the template. It is already a valid JSON string so you don't need to parse it or anything. Only when rendering it in the template, mark it as safe to prevent HTML quoting.

# views.py
def foo(request):
    time_series_json = json.dumps(time_series)
    return render(request, 
                  "template.html", 
                  context={'time_series': time_series_json})

# in the template
<script>
    const timeSeries = {{ time_series | safe }};
</script>
Milan Cermak
  • 7,476
  • 3
  • 44
  • 59
  • This isn't strictly true. A JSON string is meant to be rendered inside a string, not as a general JSON object like an array or map. For example, if you use your method to render a map, it's going to be corrupted since it'll render all keys and values with a backslash to escape it's quotes for use inside a string. This might work for arrays containing only numbers, since they won't need any escaping, but that's a niche case. – Cerin Dec 05 '19 at 20:28
4

Using the Django templates built-in filter json_script:

In views.py:

render(request, "foo.html", {'time_series_data': time_series})

In the template foo.html:

{{ time_series_data|json_script:"time-series-data" }}

In your script:

const timeSeriesData = JSON.parse(document.getElementById('time-series-data').textContent);
talz
  • 1,004
  • 9
  • 22
  • I tried and after parsing the JSON, when I try to get the keys I get every character of the JSON as key, it doesn't recognize the JSON keys. What's going on? – Carlitos_30 Nov 24 '22 at 15:51
  • See this: https://stackoverflow.com/questions/74563785/passing-a-json-object-from-django-to-javascript-doesnt-work-properly/74563861#74563861 – Carlitos_30 Nov 24 '22 at 16:54
2

have you tried passing something like json.dumps(time_series) to the render function?

Romeo Mihalcea
  • 9,714
  • 12
  • 50
  • 102