154 votes

Comment puis-je passer des données de Flask à JavaScript dans un modèle ?

Mon application fait appel à une API qui renvoie un dictionnaire. Je veux transmettre des informations de ce dict à JavaScript dans la vue. J'utilise l'API Google Maps en JS, donc j'aimerais lui transmettre une liste de tuples avec les informations de longitude/latitude. Je sais que render_template transmettra ces variables à la vue pour qu'elles puissent être utilisées dans HTML, mais comment pourrais-je les transmettre à JavaScript dans le modèle ?

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)

190voto

mensi Points 4316

Vous pouvez utiliser {{ variable }} n'importe où dans votre modèle, pas seulement dans la partie HTML. Donc cela devrait fonctionner:

    var someJavaScriptVar = '{{ geocode[1] }}';

  Hello World

Pensez-y comme un processus en deux étapes: Tout d'abord, Jinja (le moteur de templates utilisé par Flask) génère votre sortie de texte. Cela est envoyé à l'utilisateur qui exécute le JavaScript qu'il voit. Si vous voulez que votre variable Flask soit disponible en JavaScript en tant qu'array, vous devez générer une définition d'array dans votre sortie:

      var myGeocode = ['{{ geocode[0] }}', '{{ geocode[1] }}'];

    Hello World

Jinja offre également des contructs plus avancés provenant de Python, vous pouvez donc le raccourcir à:

    var myGeocode = [{{ ', '.join(geocode) }}];

  Hello World

Vous pouvez également utiliser des boucles for, des déclarations if et bien plus encore, voir la documentation de Jinja2 pour plus d'informations.

Jetez également un coup d'œil à la réponse de Ford qui mentionne le filtre tojson qui est une addition à l'ensemble standard de filtres de Jinja2.

Édition nov 2018: tojson est désormais inclus dans l'ensemble standard de filtres de Jinja2.

137voto

ford Points 1891

La meilleure façon d'obtenir à peu près n'importe quel objet Python dans un objet JavaScript est d'utiliser JSON. JSON est idéal en tant que format de transfert entre les systèmes, mais parfois nous oublions qu'il signifie JavaScript Object Notation. Cela signifie que l'injection JSON dans le modèle est la même que l'injection de code JavaScript décrivant l'objet.

Flask fournit un filtre Jinja pour cela : tojson sérialise la structure en une chaîne JSON et la marque comme sécurisée pour que Jinja ne l'échappe pas automatiquement.

      var myGeocode = {{ geocode|tojson }};

    Bonjour le monde

Cela fonctionne pour toute structure Python qui est sérialisable en JSON :

python_data = {
    'some_list': [4, 5, 6],
    'nested_dict': {'foo': 7, 'bar': 'une chaîne'}
}

var data = {{ python_data|tojson }};
alert('Données : ' + data.some_list[1] + ' ' + data.nested_dict.foo + 
      ' ' + data.nested_dict.bar);

41voto

mcote Points 21

En utilisant un attribut de données sur un élément HTML, vous évitez d'avoir à utiliser un script en ligne, ce qui signifie que vous pouvez utiliser des règles CSP plus strictes pour une sécurité accrue.

Spécifiez un attribut de données comme ceci :

...

Ensuite, accédez-y dans un fichier JavaScript statique comme ceci :

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

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

15voto

Vinnie James Points 2167

Vous pouvez également ajouter un point de terminaison pour renvoyer votre variable :

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

Ensuite, effectuez une requête XHR pour la récupérer :

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

2 votes

Oui, vous pourriez le faire, et dans certaines architectures (notamment les SPAs), c'est la bonne façon de faire, mais gardez à l'esprit qu'il existe plusieurs inconvénients à le faire plutôt que d'intégrer les données dans la page lors de sa diffusion : 1. c'est plus lent, 2. cela nécessite un peu plus de code même pour le faire négligemment, et 3. cela introduit au moins deux états frontaux supplémentaires que vous devrez probablement gérer correctement dans votre interface utilisateur (à savoir l'état où la requête XHR est toujours en cours, et celui où elle a échoué complètement), ce qui nécessite beaucoup de code JavaScript supplémentaire et introduit une source supplémentaire de bogues potentiels.

6voto

Patrick Mutuku Points 139

Les réponses de travail sont déjà données mais je veux ajouter une vérification qui agit comme une sécurité en cas où la variable flask n'est pas disponible. Lorsque vous utilisez :

var myVariable = {{ flaskvar | tojson }};

s'il y a une erreur qui rend la variable inexistante, les erreurs résultantes peuvent produire des résultats inattendus. Pour éviter cela :

{% if flaskvar is defined and flaskvar %}
var myVariable = {{ flaskvar | tojson }};
{% endif %}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X