[javascript] How to pass a list from Python, by Jinja2 to JavaScript

Let's say I have a Python variable:

list_of_items = ['1','2','3','4','5']

and I pass it to Jinja by rendering HTML, and I also have a function in JavaScript called somefunction(variable). I am trying to pass each item of list_of_items. I tried something like this:

{% for item in list_of_items %}
<span onclick="somefunction({{item}})">{{item}}</span><br>
{% endfor %}

Is it possible to pass a list from Python to JavaScript or should I pass each item from list one by one in a loop? How can I do this?

This question is related to javascript python variables jinja2

The answer is


You can do this with Jinja's tojson filter, which

Dumps a structure to JSON so that it’s safe to use in <script> tags [and] in any place in HTML with the notable exception of double quoted attributes.

For example, in your Python, write:

some_template.render(list_of_items=list_of_items)

... or, in the context of a Flask endpoint:

return render_template('your_template.html', list_of_items=list_of_items)

Then in your template, write this:

{% for item in list_of_items %}
<span onclick='somefunction({{item | tojson}})'>{{item}}</span><br>
{% endfor %}

(Note that the onclick attribute is single-quoted. This is necessary since |tojson escapes ' characters but not " characters in its output, meaning that it can be safely used in single-quoted HTML attributes but not double-quoted ones.)

Or, to use list_of_items in an inline script instead of an HTML attribute, write this:

<script>
const jsArrayOfItems = {{list_of_items | tojson}};
// ... do something with jsArrayOfItems in JavaScript ...
</script>

DON'T use json.dumps to JSON-encode variables in your Python code and pass the resulting JSON text to your template. This will produce incorrect output for some string values, and will expose you to XSS if you're trying to encode user-provided values. This is because Python's built-in json.dumps doesn't escape characters like < and > (which need escaping to safely template values into inline <script>s, as noted at https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements) or single quotes (which need escaping to safely template values into single-quoted HTML attributes).

If you're using Flask, note that Flask injects a custom tojson filter instead of using Jinja's version. However, everything written above still applies. The two versions behave almost identically; Flask's just allows for some app-specific configuration that isn't available in Jinja's version.


Make some invisible HTML tags like <label>, <p>, <input> etc. and name its id, and the class name is a pattern so that you can retrieve it later.

Let you have two lists maintenance_next[] and maintenance_block_time[] of the same length, and you want to pass these two list's data to javascript using the flask. So you take some invisible label tag and set its tag name is a pattern of list's index and set its class name as value at index.

_x000D_
_x000D_
{% for i in range(maintenance_next|length): %}_x000D_
<label id="maintenance_next_{{i}}" name="{{maintenance_next[i]}}" style="display: none;"></label>_x000D_
<label id="maintenance_block_time_{{i}}" name="{{maintenance_block_time[i]}}" style="display: none;"></label>_x000D_
{% endfor%}
_x000D_
_x000D_
_x000D_

Now you can retrieve the data in javascript using some javascript operation like below -

_x000D_
_x000D_
<script>_x000D_
var total_len = {{ total_len }};_x000D_
 _x000D_
for (var i = 0; i < total_len; i++) {_x000D_
    var tm1 = document.getElementById("maintenance_next_" + i).getAttribute("name");_x000D_
    var tm2 = document.getElementById("maintenance_block_time_" + i).getAttribute("name");_x000D_
    _x000D_
    //Do what you need to do with tm1 and tm2._x000D_
    _x000D_
    console.log(tm1);_x000D_
    console.log(tm2);_x000D_
}_x000D_
</script>
_x000D_
_x000D_
_x000D_


I can suggest you a javascript oriented approach which makes it easy to work with javascript files in your project.

Create a javascript section in your jinja template file and place all variables you want to use in your javascript files in a window object:

Start.html

...
{% block scripts %}
<script type="text/javascript">
window.appConfig = {
    debug: {% if env == 'development' %}true{% else %}false{% endif %},
    facebook_app_id: {{ facebook_app_id }},
    accountkit_api_version: '{{ accountkit_api_version }}',
    csrf_token: '{{ csrf_token }}'
}
</script>
<script type="text/javascript" src="{{ url_for('static', filename='app.js') }}"></script>
{% endblock %}

Jinja will replace values and our appConfig object will be reachable from our other script files:

App.js

var AccountKit_OnInteractive = function(){
    AccountKit.init({
        appId: appConfig.facebook_app_id,
        debug: appConfig.debug,
        state: appConfig.csrf_token,
        version: appConfig.accountkit_api_version
    })
}

I have seperated javascript code from html documents with this way which is easier to manage and seo friendly.


To add up on the selected answer, I have been testing a new option that is working too using jinja2 and flask:

@app.route('/')
def my_view():
    data = [1, 2, 3, 4, 5]
    return render_template('index.html', data=data)

The template:

<script>
    console.log( {{ data | tojson }} )
</script>

the output of the rendered template:

<script>
    console.log( [1, 2, 3, 4] )
</script>

The safe could be added but as well like {{ data | tojson | safe }} to avoid html escape but it is working without too.


I had a similar problem using Flask, but I did not have to resort to JSON. I just passed a list letters = ['a','b','c'] with render_template('show_entries.html', letters=letters), and set

var letters = {{ letters|safe }}

in my javascript code. Jinja2 replaced {{ letters }} with ['a','b','c'], which javascript interpreted as an array of strings.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to variables

When to create variables (memory management) How to print a Groovy variable in Jenkins? What does ${} (dollar sign and curly braces) mean in a string in Javascript? How to access global variables How to initialize a variable of date type in java? How to define a variable in a Dockerfile? Why does foo = filter(...) return a <filter object>, not a list? How can I pass variable to ansible playbook in the command line? How do I use this JavaScript variable in HTML? Static vs class functions/variables in Swift classes?

Examples related to jinja2

'if' statement in jinja2 template Ansible: filter a list by its attributes Split string into list in jinja? How to iterate through a list of dictionaries in Jinja template? How to write dynamic variable in Ansible playbook Jinja2 template not rendering if-elif-else statement properly Jinja2 template variable if None Object set a default value Convert integer to string Jinja Link to Flask static files with url_for How to pass a list from Python, by Jinja2 to JavaScript