Flask: pythonからjsへ変数を受け渡す方法(inline script/ 外部scriptファイル)

flask
この記事は約6分で読めます。

flaskというかjinja2の関係の記事になりますが、pythonでサーバサイドで作成したオブジェクト(今回はlist data)をjs側で取り扱う方法について説明していきます。

今遊びで作っているflaskで作るMeetingコストを随時計算して表示する(よくあるjsの初級者課題ですね)アプリの実装に置いて、どうしてもjs側にpython側からデータを受け渡す必要があったので、そのやり方の説明です。

Advertisements

やることの概要

イメージとしては、以下のような処理になります。

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の方が楽だと思うツールではありますが。。)

コメント