La mia app effettua una chiamata a un'API che restituisce un dizionario. Voglio passare le informazioni da questo dettato a JavaScript nella vista. Sto utilizzando l'API di Google Maps nel JS, in particolare, quindi mi piacerebbe passargli una lista di tuple con le informazioni long/lat. So che render_template
passerà queste variabili alla vista in modo che possano essere utilizzate in HTML, ma come potrei passarle a JavaScript nel modello?Come posso passare i dati da Flask a JavaScript in un modello?
risposta
È possibile utilizzare {{ variable }}
in qualsiasi punto del modello, non solo nella parte HTML. Quindi questo dovrebbe funzionare:
<html>
<head>
<script>
var someJavaScriptVar = '{{ geocode[1] }}';
</script>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: {{ geocode[0] }} ' + someJavaScriptVar)" />
</body>
</html>
pensare ad esso come un processo in due fasi: in primo luogo, Jinja (il motore di template Flask usa) genera l'output di testo. Questo viene inviato all'utente che esegue il codice JavaScript che vede. Se si desidera che la variabile Flask sia disponibile in JavaScript come un array, è necessario generare una definizione di matrice nell'output:
<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 offre anche costrutti più avanzati in pitone, in modo da poter ridurre a:
<html>
<head>
<script>
var myGeocode = [{{ ', '.join(geocode) }}];
</script>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>
È inoltre possibile utilizzare for
loop, if
dichiarazioni e molti di più, vedere la Jinja2 documentation di più.
Dai un'occhiata anche alla risposta di Ford che indica il filtro tojson
che è un'aggiunta a Jinja2's standard set of filters.
Il modo ideale per ottenere praticamente qualsiasi oggetto Python in un oggetto JavaScript è utilizzare JSON. JSON è ottimo come formato per il trasferimento tra sistemi, ma a volte ci dimentichiamo che sta per JavaScript Object Notation. Ciò significa che l'iniezione di JSON nel modello equivale a iniettare il codice JavaScript che descrive l'oggetto.
Flask fornisce un filtro Jinja per questo: tojson
scarica la struttura in una stringa JSON e la contrassegna in modo sicuro in modo che Jinja non la esegua automaticamente.
<html>
<head>
<script>
var myGeocode = {{ geocode|tojson }};
</script>
</head>
<body>
<p>Hello World</p>
<button onclick="alert('Geocode: ' + myGeocode[0] + ' ' + myGeocode[1])" />
</body>
</html>
Questo funziona per qualsiasi struttura Python che è JSON serializzabile:
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);
Prova questo la prossima volta che si ottiene 'SyntaxError Uncaught: token imprevisto e' nella console JavaScript. – bahmait
Solo un'altra soluzione alternativa per coloro che vogliono passare variabili a uno script, che è di provenienza con pallone, solo io è riuscito a farlo funzionare definendo le variabili all'esterno e chiamando lo script come segue:
<script>
var myfileuri = "/static/my_csv.csv"
var mytableid = 'mytable';
</script>
<script type="text/javascript" src="/static/test123.js"></script>
Se inserisco le variabili jinja in test123.js
, non funziona e si otterrà un errore.
Esattamente quello che stavo cercando. – shrishinde
In alternativa si potrebbe aggiungere un endpoint per restituire la variabile:
@app.route("/api/geocode")
def geo_code():
return jsonify(geocode)
Poi fare un XHR per recuperarlo:
fetch('/api/geocode')
.then((res)=>{ console.log(res) })
Utilizzando un data attribute su un elemento HTML evita di dover utilizzare script inline , che a sua volta significa che è possibile utilizzare stricter CSP rules per una maggiore sicurezza.
Specificare un attributo di dati in questo modo:
<div id="mydiv" data-geocode="{{ geocode|tojson }}">...</div>
Poi accedervi in un JavaScript statica file in questo modo:
// Raw JavaScript
var geocode = JSON.parse(document.getElementById("mydiv").dataset.geocode);
// jQuery
var geocode = JSON.parse($("#mydiv").data("geocode"));
Alcuni js file provenienti dal Web o in biblioteca, non sono scritte da solo. Il codice ottengono variabile in questo modo:
var queryString = document.location.search.substring(1);
var params = PDFViewerApplication.parseQueryString(queryString);
var file = 'file' in params ? params.file : DEFAULT_URL;
This method rende i file invariato (mantenere l'indipendenza) js, e passare correttamente variabile!
Molto obbligato, Mensi! Questo è stato il mio pensiero iniziale, ma la documentazione di Flask non rende facilmente chiaro che è possibile utilizzare anche il modulo {{var}} in JS. Grazie per averlo chiarito. – mea
@mea: è anche possibile utilizzare il motore di template per generare file basati su testo arbitrarie, ho anche usato per generare dinamicamente i file TeX (-> PDF) ed e-mail, è molto versatile;) – mensi
rapido follow-up domanda: se io fai un ciclo for in JS, posso usare la variabile index all'interno della variabile python es {{geocode [i]}}? – mea