2012-06-24 26 views
71

Ứng dụng của tôi thực hiện cuộc gọi đến API trả về từ điển. Tôi muốn chuyển thông tin từ dict này sang JavaScript trong khung nhìn. Tôi đang sử dụng API Google Maps trong JS, đặc biệt, vì vậy tôi muốn chuyển nó một danh sách các bộ dữ liệu với thông tin dài/lat. Tôi biết rằng render_template sẽ chuyển các biến này vào chế độ xem để chúng có thể được sử dụng trong HTML, nhưng làm thế nào tôi có thể chuyển chúng vào JavaScript trong mẫu?Làm cách nào để chuyển dữ liệu từ Flask sang JavaScript trong mẫu?

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) 

Trả lời

94

Bạn có thể sử dụng {{ variable }} bất kỳ nơi nào trong mẫu của mình, không chỉ trong phần HTML. Vì vậy, điều này sẽ hoạt động:

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

Hãy coi đó là quy trình hai giai đoạn: Trước tiên, Jinja (công cụ tạo mẫu sử dụng Flask) tạo ra kết quả văn bản của bạn. Điều này được gửi đến người dùng thực thi JavaScript mà anh ta thấy. Nếu bạn muốn biến Flask của bạn sẽ có sẵn trong JavaScript là một mảng, bạn phải tạo ra một định nghĩa mảng trong đầu ra của bạn:

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

Jinja cũng cung cấp các cấu trúc tiên tiến hơn từ Python, do đó bạn có thể rút ngắn nó để:

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

Bạn cũng có thể sử dụng for vòng, if báo cáo và nhiều hơn nữa, xem Jinja2 documentation để biết thêm.

Ngoài ra, hãy xem câu trả lời của người đã chỉ ra bộ lọc tojson là một bổ sung cho Jinja2's standard set of filters.

+1

Nhiều nghĩa vụ, mensi! Đó là suy nghĩ ban đầu của tôi nhưng tài liệu cho Flask không làm cho nó dễ dàng rõ ràng rằng bạn cũng có thể sử dụng biểu mẫu {{var}} trong JS. Cám ơn giải thích rõ ràng. – mea

+2

@mea: bạn cũng có thể sử dụng mẫu động cơ để tạo ra tập tin văn bản dựa trên tùy ý, tôi cũng đã sử dụng nó để tự động tạo ra file TeX (-> PDF) và e-mail, nó khá linh hoạt;) – mensi

+0

nhanh chóng theo dõi câu hỏi: nếu tôi làm một vòng lặp for trong JS, tôi có thể sử dụng biến chỉ mục trong biến python ví dụ {{mã địa lý [i]}}? – mea

64

Cách lý tưởng để đi về việc nhận được khá nhiều đối tượng Python vào đối tượng JavaScript là sử dụng JSON. JSON là một định dạng tuyệt vời để chuyển giữa các hệ thống, nhưng đôi khi chúng ta quên rằng nó là viết tắt của JavaScript Object Notation. Điều này có nghĩa là việc đưa JSON vào khuôn mẫu giống như việc tiêm mã JavaScript mô tả đối tượng.

Bình cung cấp bộ lọc Jinja cho việc này: tojson đổ cấu trúc vào chuỗi JSON và đánh dấu nó an toàn để Jinja không tự động cảnh báo nó.

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

này làm việc cho bất kỳ cấu trúc Python đó là JSON serializable:

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); 
+2

Hãy thử điều này trong lần tiếp theo bạn nhận được 'Uncaught SyntaxError: Unexpected token &' trong bảng điều khiển javascript. – bahmait

2

Chỉ cần một giải pháp thay thế cho những ai muốn vượt qua các biến để một kịch bản mà có nguồn gốc sử dụng bình, tôi chỉ quản lý để làm việc này bằng cách xác định các biến bên ngoài và sau đó gọi tập lệnh như sau:

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

Nếu tôi nhập các biến jinja vào test123.js, nó sẽ không hoạt động và bạn sẽ gặp lỗi.

+0

Chính xác những gì tôi đang tìm kiếm. – shrishinde

2

Ngoài ra bạn có thể thêm một thiết bị đầu cuối để trở biến của bạn:

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

Sau đó làm một XHR để lấy nó:

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

Sử dụng một data attribute trên một phần tử HTML tránh được việc phải sử dụng kịch bản nội tuyến , điều này có nghĩa là bạn có thể sử dụng stricter CSP rules để tăng cường bảo mật.

Chỉ định một thuộc tính dữ liệu như vậy:

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

Sau đó truy cập vào nó trong một hoạt Javascript tĩnh nộp như sau:

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

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

Một số js file đến từ các trang web hoặc thư viện, họ không viết một mình. Mã này họ nhận được biến như thế này:

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

This method làm js file không thay đổi (giữ độc lập), và vượt qua biến một cách chính xác!

Các vấn đề liên quan