【问题标题】:Passing a JSON object from Flask to JavaScript将 JSON 对象从 Flask 传递到 JavaScript
【发布时间】:2017-02-28 03:15:18
【问题描述】:

我在将 Flask/Python 变量传递给 Javascript 时遇到了麻烦。

基本上,我从 MySQL 导入并尝试以三种不同的方式呈现返回。

  1. (43.8934276, -103.3690243), (47.052060, -91.639868), (45.1118, -95.0396) 这是我的 dict 项目在其上运行以下内容时的输出。

new_list = [tuple(d.values()) for d in MySQL_Dict] output = ', '.join('(' + ', '.join(i) + ')' for i in new_list)

这个方法不好,但是我添加了它是为了详细,它的格式根本不正确。

  1. 我将 python dict 直接传递给看起来像这样的模板

({'lat': '43.8934276', 'lng': '-103.3690243'}, {'lat': '47.052060', 'lng': '-91.639868'}, {'lat': '45.1118', 'lng': '-95.0396'})

然后在模板方面我尝试了以下 JavaScript 行

 var other_coords = {{ MySQL_Dict|tojson }}; 
 var other_coords = {{ MySQL_Dict|tojson|safe }};
 var still_more = JSON.parse(other_coords);

这些都不起作用,一起或单独。

  1. 我还尝试使用json_out = json.dumps(My_Dict) 从视图中发送字典,但这也不起作用。

这一切都是为了将​​ lat、lng 坐标从 MySQL DB 获取到 Google Maps API 脚本。让我感到困惑的是,如果我只是将视图中的 json.dump 结果粘贴到 Google Maps 脚本中,它可以完美地工作(在删除引号之后),但是如果我使用变量,它将对我不起作用。有人有建议吗?

【问题讨论】:

  • 呈现的 HTML 中期望的输出是什么?
  • 谷歌地图上的标记。
  • 抱歉,我的意思是您要查找什么输出格式(坐标)?
  • 哦,抱歉,它需要看起来像这样,只是一个 JavaScript 对象,对吗?我认为您可以通过使用 JSON.parse(json_object) 从 JSON 中获得哪个? [{lat: 43.8934276, lng: -103.3690243}, {lat: 47.052060, lng: -91.639868}, {lat: 45.1118, lng: -95.0396}]

标签: javascript python google-maps flask jinja2


【解决方案1】:

目前接受的答案(@BrettJ)似乎存在一个可能的安全漏洞:如果我们传递给 javascript 的对象有一些内部带有单引号的字符串,则该单引号不会被 json.dumps 转义,从而允许将任意代码注入 javascript。最好使用 Flask 的 tojson() 模板过滤器,请参阅 the docs,因为它可以正确转义所有此类字符(将它们替换为 unicode 代码)。

这是我的解决方案:

view.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    user = {'firstname': "Mr.", 'lastname': "My Father's Son"}
    return render_template("index.html", user=user)

if __name__ == '__main__':
    app.run()

index.html

<p>Hello, <span id="username"></span></p>
<script>
    var user = JSON.parse('{{ user | tojson | safe}}');
    document.getElementById('username').innerHTML = user.firstname + " " +
            user.lastname;
</script>

生成的 JS 看起来像:

var user = JSON.parse('{"firstname": "Mr.", "lastname": "My Father\u0027s Son"}');

这是绝对安全的。例如,如果我们使用json.dumps-powered 解决方案,我们会得到 ​​p>

var user = JSON.parse('{"firstname": "Mr.", "lastname": "My Father's Son"}');

这在语法上是不正确的(至少可以这么说)。

【讨论】:

  • 你的答案对我有用。我改变了我接受的答案,更好的安全性总是等于更好的代码。
  • 非常感谢!你为我节省了很多时间! :)
  • 这行JSON.parse('{{ user | tojson | safe}}') 正是我所需要的。单引号也有帮助!
  • 我很想弄清楚@Ilya V. Schurov 提出的安全漏洞点(“这个单引号不会被 json.dumps 转义,因此允许将任意代码注入 javascript” )。您指出漏洞在于 json 转储本身传递的未转义代码本身可以是可注入 javascript 的代码。对吗?
  • @hbrannan 是的,入侵者可以将恶意 javascript 代码放入他们设置的字段(即注册期间的用户名,或消息文本或其他内容)中,并且此代码可以窃取 cookie/会话等.
【解决方案2】:

下面的简单示例应该显示如何从您的 dict 中获取 Javascript 对象:

views.py

@app.route('/', methods=['GET','POST'])                                         
def index():                                                                    

    points = [{"lat": 43.8934276, "lng": -103.3690243},                         
              {"lat": 47.052060, "lng": -91.639868},                            
              {"lat": 45.1118, "lng": -95.0396}]                                

    return render_template("index.html", points=json.dumps(points)) 

index.html(为简洁起见,删除了一些代码)

  function initMap() {                                                      

    var map = new google.maps.Map(document.getElementById('map'), {         
      center: new google.maps.LatLng(43.8934276, -103.3690243),             
      zoom: 4                                                               
    });                                                                     

    var points = JSON.parse('{{ points|safe }}');                           
    var marker;                                                             

    for (var i = 0; i < points.length; i++) {                               

        marker = new google.maps.Marker({                                   
          position: new google.maps.LatLng(points[i].lat, points[i].lng),   
          map: map                                                          
        });                                                                 

    }                                                                       
  }   

【讨论】:

  • 感谢您的回答!好的,为什么会这样?如果我按照你说的做所有事情,标记不会出现在地图上。在谷歌地图中,​​我只是设置var locations = points; 但是,如果我复制并粘贴您定义的点变量的输出,并将var locations = [{lat: 43.8934276,lng: -103.3690243 },{lat: 47.05206,lng: -91.639868}, {lat:45.1118,lng: -95.0396 }] 直接执行到地图脚本中,它就完美了!......我很困惑.
  • 我添加了一些示例 Javascript 用于在地图上呈现标记。在本地测试,它为我呈现标记。希望这会有所帮助!
  • 你先生是神!太感谢了。我一直以来最大的问题是实际的地图脚本本身......多么令人失望。非常感谢!
  • 另外,请注意遇到此问题的自己和/或未来的人。我的变量中有一个 JS 不喜欢的下划线。一旦我改变了这一点,事情就会变得更好。我从不写 JS,所以我不确定这是规则或语法问题还是什么。无论如何,再次感谢马特。
  • 由于缺少单引号字符的转义,此解决方案存在安全问题(可能是任意 javascript 代码注入)。最好使用tojson Flask 模板过滤器。详情见我的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-28
  • 2012-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多