Как я могу передать данные из Flask в JavaScript в шаблоне?
мое приложение вызывает API, который возвращает словарь. Я хочу передать информацию из этого dict в JavaScript в представлении. Я использую API Карт Google в JS, в частности, поэтому я хотел бы передать ему список кортежей с информацией 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)
7 ответов:
можно использовать
{{ 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 (использует колбу template engine) генерирует ваш текстовый вывод. Это отправляется пользователю, который выполняет 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.
идеальный способ получить практически любой объект Python в объект JavaScript - использовать JSON. JSON отлично подходит в качестве формата для передачи между системами, но иногда мы забываем, что он означает обозначение объекта JavaScript. Это означает, что введение JSON в шаблон совпадает с введением кода JavaScript, описывающего объект.
колба обеспечивает фильтр Jinja для этого:
tojson
сбрасывает структуру в строку JSON и помечает ее безопасно, поэтому что Дзиндзя не autoescape его.<html> <head> <script> var myGeocode = {{ geocode|tojson }}; </script> </head> <body> <p>Hello World</p> <button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" /> </body> </html>
это работает для любой структуры Python, которая является сериализуемой JSON:
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);
С помощью атрибуты на 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"));
в качестве альтернативы вы можете добавить конечную точку для возврата переменной:
@app.route("/api/geocode") def geo_code(): return jsonify(geocode)
затем сделайте XHR, чтобы получить его:
fetch('/api/geocode') .then((res)=>{ console.log(res) })
просто еще одно альтернативное решение для тех, кто хочет передать переменные в скрипт, который получен с помощью flask, мне удалось получить эту работу, определив переменные снаружи, а затем вызвав скрипт следующим образом:
<script> var myfileuri = "/static/my_csv.csv" var mytableid = 'mytable'; </script> <script type="text/javascript" src="/static/test123.js"></script>
Если я ввожу переменные jinja в
test123.js
это не сработает, и вы получите сообщение об ошибке.
рабочие ответы уже даны, но я хочу добавить проверку, которая действует как отказоустойчивая в случае, если переменная flask недоступна. При использовании:
var myVariable = {{ flaskvar | tojson }};
Если есть ошибка, которая приводит к тому, что переменная не существует, результирующие ошибки могут привести к неожиданным результатам. Чтобы избежать этого:
{% if flaskvar is defined and flaskvar %} var myVariable = {{ flaskvar | tojson }}; {% endif %}
некоторые JS файлы приходят из интернета или библиотеки, они не пишутся сами. Код они получают переменную, как это:
var queryString = document.location.search.substring(1); var params = PDFViewerApplication.parseQueryString(queryString); var file = 'file' in params ? params.file : DEFAULT_URL;
этот метод делает файлы js неизменными (сохраняет независимость) и правильно передает переменную!