如何通过 Jinja2 从 Python 传递列表到 JavaScript
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15321431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass a list from Python, by Jinja2 to JavaScript
提问by user1843766
Let's say I have a Python variable:
假设我有一个 Python 变量:
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:
我通过渲染 HTML 将它传递给 Jinja,我在 JavaScript 中还有一个名为somefunction(variable). 我正在尝试通过list_of_items. 我试过这样的事情:
{% 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?
是否可以将列表从 Python 传递给 JavaScript,还是应该循环传递列表中的每个项目?我怎样才能做到这一点?
采纳答案by mdeous
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 safeJinja filter, to prevent your data from being htmlescaped.
要将一些上下文数据传递给 javascript 代码,您必须以一种 javascript(即 JSON)“理解”的方式对其进行序列化。您还需要使用safeJinja 过滤器将其标记为安全,以防止您的数据被 html 转义。
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
编辑 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)
编辑 3(安全警告)
NEVER EVER DO THIS WITH USER-SUPPLIED DATA, ONLY DO THIS WITH TRUSTED DATA!
切勿使用用户提供的数据执行此操作,仅使用受信任的数据执行此操作!
Otherwise, you would expose your application to XSS vulnerabilities!
否则,您的应用程序就会暴露于 XSS 漏洞!
回答by Godsmith
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。我只是通过一个列表letters = ['a','b','c']与render_template('show_entries.html', letters=letters)和集
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 替换{{ letters }}为['a','b','c'],javascript 将其解释为字符串数组。
回答by muratgozel
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 文件中使用的变量放在一个 window 对象中:
Start.html
开始.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
应用程序.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.
我用这种更易于管理和 seo 友好的方式将 javascript 代码从 html 文档中分离出来。
回答by Sylhare
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 safecould be added but as well like {{ data | tojson | safe }}to avoid html escape but it is working without too.
在safe可以添加,但也喜欢{{ data | tojson | safe }}以避免HTML逃跑,但它是工作,没有太多。
回答by Mark Amery
You can do this with Jinja's tojsonfilter, which
你可以用 Jinja 的tojson过滤器来做到这一点,它
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.
将结构转储到 JSON,以便
<script>在 HTML 中的任何位置的标签 [和] 中使用都是安全的,但双引号属性除外。
For example, in your Python, write:
例如,在您的 Python 中,编写:
some_template.render(list_of_items=list_of_items)
... or, in the context of a Flask endpoint:
...或者,在 Flask 端点的上下文中:
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 onclickattribute is single-quoted. This is necessary since |tojsonescapes 'characters but not "characters in its output, meaning that it can be safely used in single-quoted HTML attributes but not double-quoted ones.)
(请注意,该onclick属性是单引号。这是必要的,因为在其输出中|tojson转义'字符而不是"字符,这意味着它可以安全地用于单引号 HTML 属性中,但不能用于双引号属性。)
Or, to use list_of_itemsin an inline script instead of an HTML attribute, write this:
或者,要list_of_items在内联脚本中使用而不是 HTML 属性,请编写以下内容:
<script>
const jsArrayOfItems = {{list_of_items | tojson}};
// ... do something with jsArrayOfItems in JavaScript ...
</script>
DON'T use json.dumpsto 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.dumpsdoesn'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).
不要json.dumps在 Python 代码中使用JSON 编码变量并将生成的 JSON 文本传递给模板。这会为某些字符串值产生不正确的输出,并且如果您尝试对用户提供的值进行编码,则会将您暴露给 XSS。这是因为 Python 的内置json.dumps不会转义像<和>这样的字符(需要转义以将值安全地模板化为 inline <script>s,如https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for 所述-contents-of-script-elements)或单引号(需要转义以安全地将值模板化为单引号 HTML 属性)。
If you're using Flask, note that Flask injects a custom tojsonfilter 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 configurationthat isn't available in Jinja's version.
如果您使用 Flask,请注意 Flask 注入自定义tojson过滤器而不是使用 Jinja 的版本。但是,上面写的所有内容仍然适用。这两个版本的行为几乎相同;Flask 只允许一些Jinja 版本中不可用的特定于应用程序的配置。
回答by Tanmoy Datta
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.
制作一些不可见的 HTML 标签,例如<label>, <p>, <input>etc. 并命名其 id,类名是一个模式,以便您以后可以检索它。
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.
让您有两个相同长度的列表 maintenance_next[] 和 maintenance_block_time[] ,并且您想使用flask将这两个列表的数据传递给javascript。因此,您使用一些不可见的标签标签并将其标签名称设置为列表索引的模式,并将其类名称设置为索引处的值。
{% for i in range(maintenance_next|length): %}
<label id="maintenance_next_{{i}}" name="{{maintenance_next[i]}}" style="display: none;"></label>
<label id="maintenance_block_time_{{i}}" name="{{maintenance_block_time[i]}}" style="display: none;"></label>
{% endfor%}
Now you can retrieve the data in javascript using some javascript operation like below -
现在您可以使用如下所示的一些 javascript 操作检索 javascript 中的数据 -
<script>
var total_len = {{ total_len }};
for (var i = 0; i < total_len; i++) {
var tm1 = document.getElementById("maintenance_next_" + i).getAttribute("name");
var tm2 = document.getElementById("maintenance_block_time_" + i).getAttribute("name");
//Do what you need to do with tm1 and tm2.
console.log(tm1);
console.log(tm2);
}
</script>

