Как я могу передавать данные из Flask в JavaScript в шаблоне?
Мое приложение вызывает вызов API, который возвращает словарь. Я хочу передать информацию из этого dict в JavaScript в представлении. Я использую API Карт Google в JS, в частности, поэтому я хотел бы передать ему список кортежей с длинной /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)
Ответы
Ответ 1
Вы можете использовать {{ variable }}
в любом месте вашего шаблона, а не только в части HTML. Поэтому это должно работать:
<html>
<head>
<script>
var someJavaScriptVar = '{{ geocode[1] }}';
</script>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: {{ geocode[0] }} ' + someJavaScriptVar)" />
</body>
</html>
Подумайте об этом как о двухэтапном процессе: во-первых, Jinja (использует флеш-память шаблона) генерирует ваш текстовый вывод. Это отправляется пользователю, который выполняет JavaScript, который он видит. Если вы хотите, чтобы ваша переменная Flask была доступна в JavaScript в виде массива, вам нужно создать определение массива в вашем выводе:
<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 также предлагает более продвинутые конструкции из Python, поэтому вы можете сократить его до:
<html>
<head>
<script>
var myGeocode = [{{ ', '.join(geocode) }}];
</script>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>
Вы также можете использовать инструкции for
loop, if
и многие другие, см. документацию Jinja2 для получения дополнительной информации.
Также посмотрите на ответ ford, который указывает на tojson
фильтр, который является дополнением к Стандартный набор фильтров Jinja2.
Ответ 2
Идеальный способ получить почти любой объект Python в объект JavaScript - использовать JSON. JSON отлично подходит для передачи данных между системами, но иногда мы забываем, что это означает JavaScript Object Notation. Это означает, что инъекция 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>
Это работает для любой структуры 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);
Ответ 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
Еще одно альтернативное решение для тех, кто хочет передать переменные в script, который получен с использованием флэка, мне удалось получить эту работу, указав переменные за пределами, а затем вызвав script следующим образом:
<script>
var myfileuri = "/static/my_csv.csv"
var mytableid = 'mytable';
</script>
<script type="text/javascript" src="/static/test123.js"></script>
Если я ввожу переменные jinja в test123.js
, это не сработает, и вы получите сообщение об ошибке.
Ответ 5
В качестве альтернативы вы можете добавить конечную точку для возврата своей переменной:
@app.route("/api/geocode")
def geo_code():
return jsonify(geocode)
Затем выполните XHR для его получения:
fetch('/api/geocode')
.then((res)=>{ console.log(res) })
Ответ 6
Некоторые файлы js поступают из Интернета или библиотеки, они не написаны сами.
Код, который они получают, изменяется следующим образом:
var queryString = document.location.search.substring(1);
var params = PDFViewerApplication.parseQueryString(queryString);
var file = 'file' in params ? params.file : DEFAULT_URL;
Этот метод делает файлы js неизменными (сохраняйте независимость) и правильно передавайте переменные!