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

如何在模板中将数据从Flask传递到JavaScript?,javascript,python,flask,jinja2,Javascript,Python,Flask,Jinja2,我的应用程序调用返回字典的API。我想将此dict中的信息传递给视图中的JavaScript。我在JS中使用GoogleMapsAPI,特别是,所以我想向它传递一个包含long/lat信息的元组列表。我知道render\u template会将这些变量传递给视图,以便在HTML中使用,但是如何将它们传递给模板中的JavaScript from flask import Flask from flask import render_template app = Flask(__name__)

我的应用程序调用返回字典的API。我想将此dict中的信息传递给视图中的JavaScript。我在JS中使用GoogleMapsAPI,特别是,所以我想向它传递一个包含long/lat信息的元组列表。我知道
render\u 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)

您可以在模板中的任何位置使用
{{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>

var someJavaScriptVar='{{geocode[1]}}';
你好,世界

将其视为两个阶段的过程:首先,Jinja(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>

var myGeocode=['{{geocode[0]}}','{{{geocode[1]}}}'];
你好,世界

Jinja还提供了更多来自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>

var myGeocode=[{{','.join(geocode)}}];
你好,世界

您还可以使用
for
循环、
if
语句和更多语句,有关更多信息,请参阅

另外,看看福特的回答,谁指出了过滤器,这是一个额外的


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

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

Flask为此提供了一个Jinja过滤器:将结构转储到JSON字符串并将其标记为安全的,以便Jinja不会自动转义它


var myGeocode={{geocode|tojson};
你好,世界

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

python_data = {
    'some_list': [4, 5, 6],
    'nested_dict': {'foo': 7, 'bar': 'a string'}
}
var data={{python_data|tojson};
警报('Data:'+Data.some_list[1]+'+Data.nested_dict.foo+
''+数据嵌套指令栏);

对于那些希望将变量传递给使用flask源代码的脚本的人来说,这是另一种可选的解决方案,我只是通过在外部定义变量,然后按如下方式调用脚本来实现这一点:

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

var myfileuri=“/static/my_csv.csv”
var mytableid='mytable';

如果我在
test123.js
中输入jinja变量,它将不起作用,您将得到一个错误。

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

@app.route("/api/geocode")
def geo_code():
    return jsonify(geocode)
然后执行XHR以检索它:

fetch('/api/geocode')
  .then((res)=>{ console.log(res) })
在HTML元素上使用a可以避免使用内联脚本,这反过来意味着您可以使用它来提高安全性

指定数据属性,如下所示:

<div id="mydiv" data-geocode='{{ geocode|tojson }}'>...</div>
// 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文件保持不变(保持独立性),并正确传递变量

已经给出了有效答案,但我想添加一个检查,在flask变量不可用的情况下作为故障保护。 使用时:

var myVariable = {{ flaskvar | tojson }};
如果存在导致变量不存在的错误,则产生的错误可能会产生意外的结果。为了避免这种情况:

{% if flaskvar is defined and flaskvar %}
var myVariable = {{ flaskvar | tojson }};
{% endif %}

const geocodeArr=JSON.parse({{geocode | tojson}}');
控制台日志(geocodeArr);

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

好吧,我有一个棘手的方法来完成这项工作。想法如下-

在HTML正文中创建一些不可见的HTML标记,如
、、
等,并在标记id中创建一个模式,例如,在标记id中使用列表索引,在标记类名中使用列表值

这里有两个相同长度的列表,分别是maintenance_next[]和maintenance_block_time[]。我想使用flask将这两个列表的数据传递给javascript。所以我取了一些不可见的标签标记,将其标记名设置为列表索引模式,并将其类名设置为索引处的值

{%i在范围内(维护|下一个|长度):%}

{%endfor%}
非常感谢,曼西!这是我最初的想法,但是Flask的文档并没有明确说明您也可以在JS中使用{{var}}表单。谢谢您的帮助。@mea:您还可以使用模板引擎生成任意基于文本的文件,我还使用它动态生成TeX文件(->PDF)和电子邮件,它的用途非常广泛;)快速跟进问题:如果我在JS中执行for循环,我可以在python变量中使用index变量吗,例如{{geocode[I]}}?这是有道理的,但是您发布的解决方案似乎要求我在JS数组的内容中插入代码。我希望我可以更具编程性地完成这项工作,这样我可以传递一个长度可变的Python列表,JS for循环可以迭代该长度,然后将它们附加到JS数组中。抱歉,如果我说得不够清楚,但我对JS和web dev相当生疏。@RocketPingu如果您想在单独的文件中传递数据,使用
json
模块以json对象的形式转储数据通常更容易。下次在javascript控制台中获得
Uncaught SyntaxError:Unexpected token&
时,请尝试此操作。我发现此答案比接受的答案更可靠、更符合逻辑。我在运行代码时出错:
TypeError:Object of typeUndefined不是JSON可序列化的
是的,您可以,在某些体系结构(特别是SPA)中,这是正确的方法,但请记住
<script>
    const geocodeArr = JSON.parse('{{ geocode | tojson }}');
    console.log(geocodeArr);
</script>