web-dev-qa-db-de.com

Wie kann ich Daten von Flask an JavaScript in einer Vorlage übergeben?

Meine App ruft eine API auf, die ein Wörterbuch zurückgibt. Ich möchte Informationen aus diesem Diktat in der Ansicht an JavaScript übergeben. Ich verwende speziell die Google Maps-API in der JS, daher möchte ich ihr eine Liste von Tupeln mit den Long/Lat-Informationen übergeben. Ich weiß das render_template übergibt diese Variablen an die Ansicht, damit sie in HTML verwendet werden können. Wie kann ich sie jedoch in der Vorlage an JavaScript übergeben?

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)
98
mea

Sie können {{ variable }} irgendwo in Ihrer Vorlage, nicht nur im HTML-Teil. Das sollte also funktionieren:

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

Stellen Sie es sich als einen zweistufigen Prozess vor: Zuerst generiert Jinja (die Template-Engine Flask)) Ihre Textausgabe, die an den Benutzer gesendet wird, der das von ihm angezeigte JavaScript ausführt Um Ihre Flask -Variable in JavaScript als Array verfügbar zu machen, müssen Sie in Ihrer Ausgabe eine Array-Definition generieren:

<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 bietet auch fortgeschrittenere Konstrukte aus Python an. Sie können sie also verkürzen auf:

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

Sie können auch for Schleifen, if Anweisungen und vieles mehr verwenden. Weitere Informationen finden Sie in der Jinja2-Dokumentation .

Schauen Sie sich auch Fords Antwort an, die auf den Filter tojson hinweist, der eine Ergänzung zu Jinja2s Standardfiltersatz ist.

Edit Nov 2018: tojson ist jetzt im Standard-Filtersatz von Jinja2 enthalten.

117
mensi

Der ideale Weg, um so ziemlich jedes Python - Objekt in ein JavaScript-Objekt zu integrieren, ist die Verwendung von JSON. JSON ist ein großartiges Format für die Übertragung zwischen Systemen, aber manchmal vergessen wir, dass es für JavaScript Object Notation steht. Dies bedeutet, dass das Einfügen von JSON in die Vorlage dem Einfügen von JavaScript-Code entspricht, der das Objekt beschreibt.

Flask bietet hierfür einen Jinja-Filter: tojson speichert die Struktur in einem JSON-String und markiert sie als sicher, damit Jinja sie nicht automatisch maskiert.

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

Dies funktioniert für jede Python - Struktur, die mit JSON serialisiert werden kann:

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);
94
ford

Wenn Sie ein Datenattribut für ein HTML-Element verwenden, müssen Sie kein Inline-Scripting verwenden. Dies bedeutet wiederum, dass Sie strengere CSP-Regeln verwenden können, um die Sicherheit zu erhöhen.

Geben Sie ein Datenattribut wie folgt an:

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

Greifen Sie dann in einer statischen JavaScript-Datei wie folgt darauf zu:

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

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

Alternativ können Sie einen Endpunkt hinzufügen, um Ihre Variable zurückzugeben:

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

Dann machen Sie eine XHR, um es abzurufen:

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

Es werden bereits funktionierende Antworten gegeben, aber ich möchte eine Prüfung hinzufügen, die als Ausfallsicherung fungiert, falls die Variable flask nicht verfügbar ist. Wenn Sie Folgendes verwenden:

var myVariable = {{ flaskvar | tojson }};

wenn ein Fehler vorliegt, der dazu führt, dass die Variable nicht vorhanden ist, können sich daraus ergebende Fehler zu unerwarteten Ergebnissen führen. Um es zu umgehen:

{% if flaskvar is defined and flaskvar %}
var myVariable = {{ flaskvar | tojson }};
{% endif %}
3
Patrick Mutuku
<script>
    const geocodeArr = JSON.parse('{{ geocode | tojson }}');
    console.log(geocodeArr);
</script>

Dies verwendet jinja2, um das Geocode-Tupel in einen Json-String zu verwandeln, und dann das Javascript JSON.parse verwandelt das in ein Javascript-Array.

2
nackjicholson

Nur eine weitere alternative Lösung für diejenigen, die Variablen an ein Skript übergeben möchten, das mit flask erstellt wurde. Dies gelang mir, indem ich die Variablen außerhalb definierte und das Skript dann wie folgt aufrief:

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

Wenn ich Jinja-Variablen in test123.js Eingebe, funktioniert das nicht und es wird eine Fehlermeldung ausgegeben.

2
tsando