如何在模板中将数据从 Flask 传递到 JavaScript?

我的应用程序调用了一个返回字典的 API。我希望在视图中将信息从这个 dict 传递到 JavaScript。我在 JS 中使用的是 Google Maps API,所以我想传递一个包含 long/lat 信息的元组列表给它。我知道 render_template会将这些变量传递给视图,这样它们就可以在 HTML 中使用,但是如何将它们传递给模板中的 JavaScript 呢?

from flask import Flask
from flask import render_template


app = Flask(__name__)


import foo_api


api = foo_api.API('API KEY')


@app.route('/')
def get_data():
events = api.call(get_event, arg0, arg1)
geocode = event['latitude'], event['longitude']
return render_template('get_data.html', geocode=geocode)
240596 次浏览

你可以在模板的任何地方使用 \{\{ variable }},而不仅仅是在 HTML 部分:

<html>
<head>
<script>
var someJavaScriptVar = '\{\{ geocode[1] }}';
</script>
</head>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: \{\{ geocode[0] }} ' + someJavaScriptVar)" />
</body>
</html>

首先,金贾(Flask 使用的模板引擎)生成文本输出。这将发送给执行他所看到的 JavaScript 的用户。如果希望 Flask 变量以数组的形式在 JavaScript 中可用,那么必须在输出中生成一个数组定义:

<html>
<head>
<script>
var myGeocode = ['\{\{ geocode[0] }}', '\{\{ geocode[1] }}'];
</script>
</head>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>

金贾还提供了更高级的 Python 构造,因此你可以将它缩短为:

<html>
<head>
<script>
var myGeocode = [\{\{ ', '.join(geocode) }}];
</script>
</head>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>

您还可以使用 for循环、 if语句等等,更多信息请参见 Jinja2文档

另外,看看福特的答案谁指出的 tojson过滤器,这是一个补充的 Jinja2的标准过滤器

2018年11月编辑: tojson现在包含在 Jinja2的标准过滤器集中。

将几乎所有 Python 对象放入 JavaScript 对象的理想方法是使用 JSON。JSON 作为系统间传输的一种格式非常棒,但有时我们会忘记它代表的是 JSON。这意味着向模板中注入 JSON 与注入描述对象的 JavaScript 代码相同。

Flask 为此提供了一个金贾过滤器: abc1将结构转储为一个 JSON 字符串,并将其标记为安全,这样金贾就不会自动转义它。

<html>
<head>
<script>
var myGeocode = \{\{ geocode|tojson }};
</script>
</head>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>

这适用于任何 JSON 可序列化的 Python 结构:

python_data = {
'some_list': [4, 5, 6],
'nested_dict': {'foo': 7, 'bar': 'a string'}
}
var data = \{\{ python_data|tojson }};
alert('Data: ' + data.some_list[1] + ' ' + data.nested_dict.foo +
' ' + data.nested_dict.bar);

对于那些想要将变量传递给使用烧瓶来源的脚本的人来说,这只是另一种替代解决方案,我只是通过在外部定义变量,然后按照以下方式调用脚本来实现这一点:

    <script>
var myfileuri = "/static/my_csv.csv"
var mytableid = 'mytable';
</script>
<script type="text/javascript" src="/static/test123.js"></script>

如果我输入 jinja 变量在 test123.js它不工作,你会得到一个错误。

或者,您可以添加一个端点来返回您的变量:

@app.route("/api/geocode")
def geo_code():
return jsonify(geocode)

然后做一个 XHR 来检索它:

fetch('/api/geocode')
.then((res)=>{ console.log(res) })

在 HTML 元素上使用 数据属性可以避免使用内联脚本,这反过来意味着可以使用 更严格的 CSP 规则来提高安全性。

像这样指定一个数据属性:

<div id="mydiv" data-geocode='\{\{ geocode|tojson }}'>...</div>

然后像下面这样在静态 JavaScript 文件中访问它:

// Raw JavaScript
var geocode = JSON.parse(document.getElementById("mydiv").dataset.geocode);


// jQuery
var geocode = JSON.parse($("#mydiv").data("geocode"));

有些 js 文件来自 web 或库,它们不是你自己写的。 代码变量是这样的:

var queryString = document.location.search.substring(1);
var params = PDFViewerApplication.parseQueryString(queryString);
var file = 'file' in params ? params.file : DEFAULT_URL;

此方法 使 js 文件保持不变(保持独立性) ,并正确传递变量!

工作答案已经给出,但我想添加一个检查,作为一个自动防故障的情况下,烧瓶变量是不可用的。 使用时:

var myVariable = \{\{ flaskvar | tojson }};

如果存在导致变量不存在的错误,则所产生的错误可能会产生意外的结果。为了避免这种情况:

{% if flaskvar is defined and flaskvar %}
var myVariable = \{\{ flaskvar | tojson }};
{% endif %}
<script>
const geocodeArr = JSON.parse('\{\{ geocode | tojson }}');
console.log(geocodeArr);
</script>

它使用 jinja2将地理代码元组转换为 json 字符串,然后 javascript JSON.parse将其转换为 javascript 数组。

嗯,我有一个棘手的方法,这项工作的想法是这样的

在 HTML 主体中创建一些不可见的 HTML 标记,如 <label>, <p>, <input>等,并在标记 id 中创建一个模式,例如,在标记 id 中使用列表索引,在标记类名中使用列表值。

这里,我有两个长度相同的列表  維修 _ next []和維修 _ block _ time []。我想使用烧瓶将这两个列表的数据传递给 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%}

之后,我使用一些简单的 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>

很棒的帖子! 这很有帮助! 下面是我完成的伪代码:

Mypage.html

<script>
var user = \{\{username}}
</script>

Mypage.js

console.log('username = ' + user)