flaskというかjinja2の関係の記事になりますが、pythonでサーバサイドで作成したオブジェクト(今回はlist data)をjs側で取り扱う方法について説明していきます。
今遊びで作っているflaskで作るMeetingコストを随時計算して表示する(よくあるjsの初級者課題ですね)アプリの実装に置いて、どうしてもjs側にpython側からデータを受け渡す必要があったので、そのやり方の説明です。
やることの概要
イメージとしては、以下のような処理になります。

pythonでapp.routeで引数渡しをしても少しいじらないとjsでは取り扱えないので、一旦jinja(template/ htmlファイル)のscriptタグ内部で再定義する必要があります。一応直接取り扱う方法もあるのですが、今回はそちらは紹介しませんので、必要な方はドキュメント見つつ作成してみてください。
実際のファイル構成/ コード概要
ファイル構成
ファイル構成は以下のような形になります。ModelsなしのView/Templateだけのものです。
-workspace |--static |---js |--sample.js |--stylesheet |--stylesheet.css |--templates |--base.html |--test_page.html |--app.py
コード概要
app.py/ test_page.html/ sample.js の3つを説明していきます。
~app.py~
rom flask import Flask
from flask import render_template, url_for
from flask import request
app = Flask(__name__)
input_from_python = ["a","b","c"] # 渡すデータ
@app.route('/')
def index_render():
return render_template("index.html")
@app.route('/testpage')
def test_page_view():
return render_template("test_page.html", input_from_python= input_from_python) #ここで渡している
if __name__ == '__main__':
app.run(debug=True)
app.pyでは/testpageが呼び出された際に、レンダリングさせて、input_from_pythonというobjを渡しています。
~test_page.html~
{% block head %}
<script src={{ url_for("static", filename="js/sample.js") }}></script>
{% endblock %}
{% block content %}
<script type="text/javascript">
let list_data = {{ input_from_python | tojson }}; #ここでjsの変数として再定義
function add_reversed_data(){
var list2 = list_data.reverse();
document.getElementById("output_from_html").innerHTML = "new data is" + list2;
}
function add_original_data(){
document.getElementById("output_from_html2").innerHTML = "original data is" + list_data;
}
</script>
<p id="input_from_python">{{ input_from_python | tojson }}</p>
<p id="output_from_html">from_html_file</p>
<p id="output_from_html2">from_html_original</p>
<p id="output_from_js">from_js_file</p>
<p id="output_from_js2">from_js_original</p>
<button type="button" value="data_update" onclick="add_reversed_data()">test_from_html</button>
<button type="button" valu="data_add2" onclick="add_original_data()">test_from_html2</button>
<button type="button" value="data_update_from_js" onclick="add_reversed_data_from_js()">test_from_js</button>
<button type="button" value="data_add" onclick="add_data_from_js()">test_from_js_original</button>
{% endblock %}
【ここがキモ】
<script></script>内でlet list_data = {{ input_from_python | tojson }}として、pythonから受け取ったオブジェクトをlist_data変数に再定義しています。こうすることで、js側で取り扱える変数となります。
あとは、ボタンを4つほど設置して、各ボタンのonclick属性にそれぞれのjs関数(inline scriptおよびsample.js双方)のスクリプトを呼び出させています。
~sample.js~
function add_reversed_data_from_js() {
let list_data2= list_data.push("test_input_from_js");
document.getElementById("output_from_js").innerHTML = "from_js:" + list_data2;
}
function add_data_from_js(){
document.getElementById("output_from_js2").innerHTML = "from_js_original:" +list_data;
}
実行結果
実行結果をスクショで貼っておきます。
ボタンクリック前:

ボタンクリック後:

各pタグ部分にjs(inline script/ 外部script)それぞれで加工したjsの実行結果が返ってきていることがわかります。無事、jsの処理をへて実行結果をhtmlに表示させることができました。
まとめ
特に何が難しいということはないかと思いますが、jinjaを経由してjsへ変数渡しする方法の紹介でした。
別口のお願いでflaskを使ったmeetingのコスト算出ツールを作っていて、近々実装が完了する予定なので、完了し次第簡単にしたものを晒していきたいと思います。(正直全部jsの方が楽だと思うツールではありますが。。)