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

2025-01-14 08:50:00
admin
原创
104
摘要:问题描述:我的应用程序调用一个返回字典的 API。我想将此字典中的信息传递给视图中的 JavaScript。具体来说,我在 JS 中使用 Google Maps API,因此我想向其传递一个包含经度/纬度信息的元组列表。我知道这render_template会将这些变量传递给视图,以便它们可以在 HTML 中...

问题描述:

我的应用程序调用一个返回字典的 API。我想将此字典中的信息传递给视图中的 JavaScript。具体来说,我在 JS 中使用 Google Maps API,因此我想向其传递一个包含经度/纬度信息的元组列表。我知道这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)

解决方案 1:

您可以{{ 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 文档。

另外,看一下福特的回答,他指出该过滤器是Jinja2 标准过滤器集的tojson补充。

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

解决方案 2:

将几乎任何 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);

解决方案 3:

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

解决方案 4:

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

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

然后执行 XHR 来检索它:

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

解决方案 5:

已经给出了可行的答案,但我想添加一个检查,以防 flask 变量不可用时起到故障保护的作用。当您使用时:

var myVariable = {{ flaskvar | tojson }};

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

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

解决方案 6:

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

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

如果我输入 jinja 变量,test123.js它不起作用,并且您会收到错误。

解决方案 7:

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

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

解决方案 8:

嗯,我有一个巧妙的方法来完成这项工作。思路如下:

在 HTML 主体中创建一些不可见的 HTML 标签,例如<label>, <p>, <input>等,并在标签 id 中制定一个模式,例如,在标签 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%}

运行代码片段Hide results展开片段

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

运行代码片段Hide results展开片段

解决方案 9:

有些 js 文件来自网络或者库,不是你自己写的。它们获取变量的代码如下:

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

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用