python—如何在模板中将数据从flask传递到javascript?

ewm0tg9j  于 2021-08-20  发布在  Java
关注(0)|答案(9)|浏览(564)

我的应用程序调用返回字典的api。我想将此dict中的信息传递给视图中的javascript。我在js中使用GoogleMapsAPI,特别是,所以我想向它传递一个包含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)
9fkzdhlc

9fkzdhlc1#

你可以用 {{ 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>

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

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>

你也可以使用 for 循环, if 语句和更多信息,请参阅jinja2文档了解更多信息。
另外,看看福特的答案,谁指出了 tojson 该过滤器是jinja2标准过滤器集的补充。
2018年11月编辑: tojson 现在包含在jinja2的标准过滤器中。

fjnneemd

fjnneemd2#

将几乎所有python对象转换成javascript对象的理想方法是使用json。json作为系统间传输的格式非常好,但有时我们忘记了它代表javascript对象表示法。这意味着向模板中注入json与注入描述对象的javascript代码相同。
flask 为此提供一个jinja过滤器: tojson 将结构转储为json字符串并将其标记为安全的,以便jinja不会自动转义它。

<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);
jyztefdp

jyztefdp3#

在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"));
1bqhqjot

1bqhqjot4#

或者,您可以添加端点以返回变量:

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

然后执行xhr以检索它:

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

yi0zb3m45#

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

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

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

t9aqgxwy

t9aqgxwy6#

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

var myVariable = {{ flaskvar | tojson }};

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

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

inb24sb27#

<script>
    const geocodeArr = JSON.parse('{{ geocode | tojson }}');
    console.log(geocodeArr);
</script>

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

x7rlezfr

x7rlezfr8#

嗯,我有一个棘手的方法做这项工作。想法如下-
制作一些不可见的html标记,如 <label>, <p>, <input> 例如,在标记id中使用列表索引,在标记类名处使用列表值。
这里有两个相同长度的列表,分别是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%}

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

eoxn13cs9#

一些js文件来自web或库,它们不是您自己编写的。他们得到的代码变量如下:

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

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

相关问题