如何通过Jinja2将一个列表从Python传递到JavaScript

时间:2021-03-05 18:08:00

I'm new to JavaScript, and I'm dealing with a problem at the moment. Let's say I have a Python variable:

我是JavaScript新手,目前正在处理一个问题。假设我有一个Python变量:

listOfItems= ['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 'listOfItems'. I tried something like this:

通过渲染HTML,我将它传递给Jinja,我在JavaScript中也有一个名为somefunction(variable)的函数。我正在试着传递“listOfItems”的每一项。我试过这样的方法:

{% for item in listOfItems %}<br>
<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?

是否可以将一个列表从Python传递到JavaScript,还是应该在循环中逐个传递列表中的每个条目?我该怎么做呢?

4 个解决方案

#1


76  

To pass some context data to javascript code, you have to serialize it in a way it will be "understood" by javascript (namely JSON). You also need to mark it as safe using the safe Jinja filter, to prevent your data from being htmlescaped.

要将一些上下文数据传递给javascript代码,您必须以javascript“理解”的方式对其进行序列化(即JSON)。您还需要使用安全的Jinja过滤器将其标记为安全,以防止数据被htmlescape。

You can achieve this by doing something like that:

你可以通过这样做来达到这个目的:

The view

import json

@app.route('/')
def my_view():
    data = [1, 'foo']
    return render_template('index.html', data=json.dumps(data))

The template

<script type="text/javascript">
    function test_func(data) {
        console.log(data);
    }
    test_func({{ data|safe }})
</script>

Edit - exact answer

So, to achieve exactly what you want (loop over a list of items, and pass them to a javascript function), you'd need to serialize every item in your list separately. Your code would then look like this:

因此,要实现您想要的结果(对项目列表进行循环,并将它们传递给javascript函数),您需要分别序列化列表中的每个项目。你的代码会是这样的:

The view

import json

@app.route('/')
def my_view():
    data = [1, "foo"]
    return render_template('index.html', data=map(json.dumps, data))

The template

{% for item in data %}
    <span onclick=someFunction({{ item|safe }});>{{ item }}</span>
{% endfor %}

Edit 2

In my example, I use Flask, I don't know what framework you're using, but you got the idea, you just have to make it fit the framework you use.

在我的例子中,我用Flask,我不知道你用的是什么框架,但是你知道了,你只需要让它适合你用的框架。

Edit 3 (Security warning)

NEVER EVER DO THIS WITH USER-SUPPLIED DATA, ONLY DO THIS WITH TRUSTED DATA!

永远不要对用户提供的数据这样做,只对受信任的数据这样做!

Otherwise, you would expose your application to XSS vulnerabilities!

否则,您的应用程序将暴露于XSS漏洞!

#2


24  

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

我在使用Flask时遇到了类似的问题,但是我不需要使用JSON。我刚刚用render_template('show_entries ')传递了一个列表字母= ['a','b','c']。html的字母=字母),并设置

var letters = {{ letters|safe }}

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

在我的javascript代码。Jinja2用['a','b','c']取代{{字母}},javascript将其解释为字符串数组。

#3


0  

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

我可以建议您使用一种面向javascript的方法,使您的项目中使用javascript文件变得更容易。

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:

在jinja模板文件中创建一个javascript部分,并将您想要在javascript文件中使用的所有变量放在窗口对象中:

Start.html

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:

Jinja将替换值,我们的appConfig对象将从我们的其他脚本文件中获得:

App.js

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.

我已经将javascript代码从html文档中分离出来,使用这种方式更容易管理和seo友好。

#4


0  

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

为了补充所选答案,我一直在使用jinja2和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 }} but it is working without too.

可以添加安全性,但也可以添加{{data | tojson |安全},但它也可以工作。

#1


76  

To pass some context data to javascript code, you have to serialize it in a way it will be "understood" by javascript (namely JSON). You also need to mark it as safe using the safe Jinja filter, to prevent your data from being htmlescaped.

要将一些上下文数据传递给javascript代码,您必须以javascript“理解”的方式对其进行序列化(即JSON)。您还需要使用安全的Jinja过滤器将其标记为安全,以防止数据被htmlescape。

You can achieve this by doing something like that:

你可以通过这样做来达到这个目的:

The view

import json

@app.route('/')
def my_view():
    data = [1, 'foo']
    return render_template('index.html', data=json.dumps(data))

The template

<script type="text/javascript">
    function test_func(data) {
        console.log(data);
    }
    test_func({{ data|safe }})
</script>

Edit - exact answer

So, to achieve exactly what you want (loop over a list of items, and pass them to a javascript function), you'd need to serialize every item in your list separately. Your code would then look like this:

因此,要实现您想要的结果(对项目列表进行循环,并将它们传递给javascript函数),您需要分别序列化列表中的每个项目。你的代码会是这样的:

The view

import json

@app.route('/')
def my_view():
    data = [1, "foo"]
    return render_template('index.html', data=map(json.dumps, data))

The template

{% for item in data %}
    <span onclick=someFunction({{ item|safe }});>{{ item }}</span>
{% endfor %}

Edit 2

In my example, I use Flask, I don't know what framework you're using, but you got the idea, you just have to make it fit the framework you use.

在我的例子中,我用Flask,我不知道你用的是什么框架,但是你知道了,你只需要让它适合你用的框架。

Edit 3 (Security warning)

NEVER EVER DO THIS WITH USER-SUPPLIED DATA, ONLY DO THIS WITH TRUSTED DATA!

永远不要对用户提供的数据这样做,只对受信任的数据这样做!

Otherwise, you would expose your application to XSS vulnerabilities!

否则,您的应用程序将暴露于XSS漏洞!

#2


24  

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

我在使用Flask时遇到了类似的问题,但是我不需要使用JSON。我刚刚用render_template('show_entries ')传递了一个列表字母= ['a','b','c']。html的字母=字母),并设置

var letters = {{ letters|safe }}

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

在我的javascript代码。Jinja2用['a','b','c']取代{{字母}},javascript将其解释为字符串数组。

#3


0  

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

我可以建议您使用一种面向javascript的方法,使您的项目中使用javascript文件变得更容易。

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:

在jinja模板文件中创建一个javascript部分,并将您想要在javascript文件中使用的所有变量放在窗口对象中:

Start.html

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:

Jinja将替换值,我们的appConfig对象将从我们的其他脚本文件中获得:

App.js

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.

我已经将javascript代码从html文档中分离出来,使用这种方式更容易管理和seo友好。

#4


0  

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

为了补充所选答案,我一直在使用jinja2和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 }} but it is working without too.

可以添加安全性,但也可以添加{{data | tojson |安全},但它也可以工作。