Comment passer une liste de Python, par Jinja2 à JavaScript

Je suis nouveau en JavaScript, et je fais face à un problème en ce moment. Disons que j'ai une variable Python:

listOfItems= ['1','2','3','4','5']

Et je le passe à Jinja en rendant HTML, et j'ai aussi une fonction en JavaScript appelée somefunction(variable). J'essaie de passer chaque élément de 'listOfItems'. J'ai essayé quelque chose comme ceci:

{% for item in listOfItems %}<br>
<span onclick="somefunction({{item}})">{{item}}</span><br>
{% endfor %}

Est-il possible de passer une liste de Python à JavaScript ou devrais-je passer chaque élément de la liste un par un dans une boucle? Comment puis-je faire cela?

49
demandé sur fragilewindows 2013-03-10 14:54:07

4 réponses

Pour passer des données de contexte au code javascript, vous devez les sérialiser d'une manière qui sera" comprise " par javascript (à savoir JSON). Vous devez également le marquer comme sûr en utilisant le filtre safe Jinja, pour empêcher vos données d'être htmlescaped.

Vous pouvez y parvenir en faisant quelque chose comme ça:

La vue

import json

@app.route('/')
def my_view():
    data = [1, 'foo']
    return render_template('index.html', data=json.dumps(data))

Le modèle

<script type="text/javascript">
    function test_func(data) {
        console.log(data);
    }
    test_func({{ data|safe }})
</script>

Modifier - réponse exacte

Donc, pour atteindre exactement ce que vous voulez (boucle sur une liste d'éléments, et passez-les à une fonction javascript), vous devez sérialiser chaque élément de votre liste séparément. Votre code ressemblerait alors à ceci:

La vue

import json

@app.route('/')
def my_view():
    data = [1, "foo"]
    return render_template('index.html', data=map(json.dumps, data))

Le modèle

{% for item in data %}
    <span onclick=someFunction({{ item|safe }});>{{ item }}</span>
{% endfor %}

Modifier 2

Dans mon exemple, j'utilise Flask, Je ne sais pas quel framework vous utilisez, mais vous avez l'idée, il vous suffit de le faire correspondre au framework que vous utilisez.

Modifier 3 (avertissement de sécurité)

NE JAMAIS LE FAIRE AVEC DES DONNÉES FOURNIES PAR L'UTILISATEUR, NE LE FAITES QU'AVEC TRUSTED De DONNÉES!

Sinon, vous exposeriez votre application à des vulnérabilités XSS!

78
répondu mdeous 2014-02-26 08:35:53

J'ai eu un problème similaire en utilisant Flask, mais je n'ai pas eu à recourir à JSON. Je viens de passer une liste letters = ['a','b','c'] avec render_template('show_entries.html', letters=letters), et l'ensemble

var letters = {{ letters|safe }}

Dans mon code javascript. Jinja2 a remplacé {{ letters }} par ['a','b','c'], que javascript a interprété comme un tableau de chaînes.

25
répondu Godsmith 2014-03-03 21:20:51

Je peux vous suggérer une approche orientée javascript qui facilite le travail avec des fichiers javascript dans votre projet.

Créez une section javascript dans votre fichier Jinja template et placez toutes les variables que vous souhaitez utiliser dans vos fichiers javascript dans un objet window:

Commencez.html

...
{% block scripts %}
<script type="text/javascript">
window.appConfig = {
    debug: {% if env == 'development' %}true{% else %}false{% endif %},
    facebook_app_id: {{ facebook_app_id }},
    accountkit_api_version: '{{ accountkit_api_version }}',
    csrf_token: '{{ csrf_token }}'
}
</script>
<script type="text/javascript" src="{{ url_for('static', filename='app.js') }}"></script>
{% endblock %}

Jinja remplacera les valeurs et notre objet appConfig sera accessible à partir de nos autres fichiers de script:

App.js

var AccountKit_OnInteractive = function(){
    AccountKit.init({
        appId: appConfig.facebook_app_id,
        debug: appConfig.debug,
        state: appConfig.csrf_token,
        version: appConfig.accountkit_api_version
    })
}

J'ai séparé le code javascript du html documents avec cette façon qui est plus facile à gérer et seo amical.

1
répondu muratgozel 2017-01-07 11:58:13

Pour ajouter la réponse sélectionnée, j'ai testé une nouvelle option qui fonctionne aussi en utilisant jinja2 et flask:

@app.route('/')
def my_view():
    data = [1, 2, 3, 4, 5]
    return render_template('index.html', data=data)

Le modèle:

<script>
    console.log( {{ data | tojson }} )
</script>

La sortie du modèle Rendu:

<script>
    console.log( [1, 2, 3, 4] )
</script>

Le safe pourrait être ajouté mais aussi comme {{ data | tojson | safe }} mais il fonctionne sans trop.

0
répondu Sylhare 2018-04-18 16:14:10