Как я могу передать данные из 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 84

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 неизменными (сохраняет независимость) и правильно передает переменную!