88

Python 変数があるとします。

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

HTML をレンダリングして Jinja に渡します。JavaScript には という関数もありますsomefunction(variable)。の各項目を渡そうとしていますlist_of_items。私はこのようなことを試しました:

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

Python から JavaScript にリストを渡すことは可能ですか、それともリストの各項目をループで 1 つずつ渡す必要がありますか? これどうやってするの?

4

6 に答える 6

127

一部のコンテキスト データを JavaScript コードに渡すには、JavaScript (つまり JSON) が「理解」できる方法でデータをシリアル化する必要があります。safeまた、データが html エスケープされないように、Jinja フィルターを使用して安全であるとマークする必要があります。

次のようなことを行うことで、これを達成できます。

景色

import json

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

テンプレート

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

編集 - 正確な答え

したがって、目的を正確に達成するには (アイテムのリストをループして、それらを JavaScript 関数に渡す)、リスト内のすべてのアイテムを個別にシリアル化する必要があります。コードは次のようになります。

景色

import json

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

テンプレート

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

編集 2

私の例では、 を使用Flaskしています。使用しているフレームワークはわかりませんが、アイデアはわかりました。使用するフレームワークに合わせてください。

編集 3 (セキュリティ警告)

ユーザー提供のデータに対しては絶対にこれを行わないでください。信頼できるデータに対してのみ行ってください。

そうしないと、アプリケーションが XSS の脆弱性にさらされることになります。

于 2013-03-10T12:11:24.113 に答える
37

Flask を使用して同様の問題が発生しましたが、JSON に頼る必要はありませんでした。、およびセットでリストletters = ['a','b','c']を渡しましたrender_template('show_entries.html', letters=letters)

var letters = {{ letters|safe }}

私のJavaScriptコードで。Jinja2 は、javascript が文字列の配列として解釈した に置き換えられまし{{ letters }}た。['a','b','c']

于 2014-03-03T21:20:51.943 に答える
19

これは、Jinja のtojsonフィルターで行うことができます。

<script>二重引用符で囲まれた属性の注目すべき例外を除いて、HTML の任意の場所でタグ [および] で安全に使用できるように、構造を JSON にダンプします。

たとえば、Python で次のように記述します。

some_template.render(list_of_items=list_of_items)

... または、Flask エンドポイントのコンテキストでは:

return render_template('your_template.html', list_of_items=list_of_items)

次に、テンプレートに次のように記述します。

{% for item in list_of_items %}
<span onclick='somefunction({{item | tojson}})'>{{item}}</span><br>
{% endfor %}

(onclick属性は重引用符で囲まれていることに注意してください。これは、出力では文字をエスケープするが文字を|tojsonエスケープしないため必要です。つまり、一重引用符で囲まれた HTML 属性では安全に使用できますが、二重引用符で囲まれた属性では使用できません。)'"

または、list_of_itemsHTML 属性の代わりにインライン スクリプトで使用するには、次のように記述します。

<script>
const jsArrayOfItems = {{list_of_items | tojson}};
// ... do something with jsArrayOfItems in JavaScript ...
</script>

json.dumpsPython コードで変数を JSON エンコードし、結果の JSON テキストをテンプレートに渡すために使用しないでください。これにより、一部の文字列値に対して誤った出力が生成され、ユーザー提供の値をエンコードしようとすると XSS にさらされます。これは、 https://html.spec.whatwg.org/multipage/scripting.html#restrictions-forに記載されているように、Python の組み込みがandjson.dumpsのような文字をエスケープしないためです(値を安全にインラインsにテンプレート化するためにエスケープする必要があります)。 -contents-of-script-elements ) または単一引用符 (単一引用符で囲まれた HTML 属性に値を安全にテンプレート化するためにエスケープする必要があります)。<><script>

Flask を使用している場合、Flask はtojsonJinja のバージョンを使用する代わりにカスタム フィルターを挿入することに注意してください。ただし、上記の内容はすべて適用されます。2 つのバージョンの動作はほぼ同じです。Flaskでは、Jinja のバージョンでは利用できないアプリ固有の構成が許可されています。

于 2018-12-27T23:54:26.913 に答える