Getting a list from Django into Javascript as an array

Viewed 12289

I have a python list generated by my views.py in Django, and I would like to pass it to javascript in my HTML template. I cannot seem to get it into javscript as an array... I need to evaluate if the list/array contains certain numbers, but it is coming over as a string.

I am passing the list to my HTML template like this:

def get_context_data(self, **kwargs):
    context = super(dashboardView, self).get_context_data(**kwargs)
    mylist = [10,22,33,45]
    context['mylist'] = mylist
    return context

When I use:

<h1 id = "list"> {{mylist}}</h1>

it shows up on the browser as it shows up as [10,22,33,45]

Then in my template I am using javascript I have:

var mylist = document.getElementById("list").innerHTML;
for(i = 0; i < mylist.length; i++){
    console.log(mylist[i])
};

this returns in the console:

'
[
1
0
,

2
2
........

I want:

10
22
33
45

I have tried to convert to JSON in python, and parse it in javascript, but can't seem to convert this string to an array, or keep getting errors. Any ideas for the best method here?

6 Answers

If you are absolutely certain your list is safe, (by that I mean it never, ever includes anything entered by a user), it is very simple.

In your view:

context={"my_list": ["item1", "item2"]}

In your template:

{{ my_list|safe }}

Renders as:

['item1', 'item2']

For example:

{{ my_list|safe }}.forEach(item => {
  console.log(item)
})

Impressively, if you pass a string with an apostrophe, Django automatically changes the quote types, so

context = {"my_list": ["item1", "it'em2"]}

renders as (note the double-quotes):

['item1', "it'em2"]

so

{{ my_list|safe }}.forEach

still works (tested on Django 3.2.6).

Even this works:

context = {"my_list": ["item1", "it'em\"2"]}

renders as:

['item1', 'it\'em"2']

so

{{ my_list|safe }}.forEach

still works.

However, as I said at the top, if your list might include input from a user, I still wouldn't trust this approach.

In views you can make your object as a JSON object:

import json

mylistraw = [10,22,33,45]
mylist = json.dumps(mylistraw)
context = {''mylistjson': mylist}

Now you can use your object in JavaScript:

var mylist = JSON.parse("{{mylistjson}}")

You can simply use tojson tag to convert python list to js array.

It will be like -

var mylist = {{mylist|tojson}};
for(i = 0; i < mylist.length; i++){
    console.log(mylist[i])
};

Try it and let me know if any problem occurs.

Django has the json_script template tag that addresses XSS vulnerabilities by escaping the <, >, and & characters.

Django json_script docs here

In your case, a simple way is to send the list as string ','.join(mylist). And then in your templates, you could simply use split(',') in js.

views

mylist = [10,22,33,45]
context['mylist'] = ','.join([str(i) for i in mylist])

html & js

var mylist = document.getElementById("list").innerHTML;
mylist = mylist.split(',')
for(i = 0; i < mylist.length; i++){
    console.log(mylist[i])
};

Or in case your js is in the template as well

var mylist = '{{mylist}}'.split(',');
for(i = 0; i < mylist.length; i++){
    console.log(mylist[i])
};

Set the list value in JavaScript and not HTML.

<script>
var mylist = {{mylist}};
for(i = 0; i < mylist.length; i++){
    console.log(mylist[i])
};
<\ script>

You need to do this in your HTML template file and not in an external JS file.

Related