☆☆ 新着記事 ☆☆

2018年11月13日火曜日

Python Flask Javascriptで変数の受け渡し

Python、Flask/Jinja2,<- -> Javascript間で、変数の値の受け渡しにトライしてみる。
特に、Javascriptとの連携を中心に。


1. Python -> Flask/Jinja2, Python -> Javascript via Flask
まずは、基本の確認。
(ディレクトリ・ファイルの構成)
---- test.py
  |
  |---- /templates
  |           |----home.html
  |---- /static
              |----index.js
 

(1) Step1. Python App -> Templates

<test.py>
from flask import Flask, render_template, url_for, flash, redirect
app = Flask(__name__)
posts = [
  [11,12,13,14],
  [21,22,23,24],
  [31,32,33,34]
  ]
@app.route("/")
def home():
    return render_template('home.html', posts=posts)

if __name__ == '__main__':
  app.run(DEBUG=true)

home.html

<!DOCTYPE html>
<html>
<head>
<script src="{{url_for('static', filename='index.js')}}"></script>
</head>
<body>
<p>List defined in Python</P>
 {% for x in posts %}         #Python AppからTemplateへの変数渡し。
 {{x}}
 {% endfor %}
</body>
</html>

通常のhtmlでJavaScriptのファイル参照は
<script type="text/javascript" src="index.js"></script>

と<head>内に記述するが、Flaskフレームワークを使っている場合

<script src="{{url_for('static', filename='index.js')}}"></script>
と<head>内に記述する




index.js

window.onload = function(){
alert("Hello, JS.File is successfully loaded!!")  #JSが読み込まれることの確認。
}

Output:


2. Templates -> Javascript
jinja2テンプレートのhtmlのフォームデータをJavascriptで受取り、処理結果をhtmlに返す。
(普通のhtml <---> js間の受け渡しと同じ。)


test.py

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
    return render_template('index.html')
if __name__ == '__main__':
    app.run(debug=True)

index.html   


{% extends "layout.html" %}
{%block body%}
<p>Select a new car from the list.</p>
<select id="mySelect" onchange="myFunction()"> #JS Functionの呼び出し。 Form値の受け渡し。
  <option value="Audi">Audi
  <option value="BMW">BMW
  <option value="Mercedes">Mercedes
  <option value="Volvo">Volvo
</select>

<p>When you select a new car, a function is triggered which outputs the value of the selected car.</p>

<p id="demo"></p>

<script type="text/javascript" src="{{ url_for('static', filename='../static/hello.js') }}">
</script>
{%endblock%}

layout.html
<!doctype html>
<title>Javascript example</title>
{% block body %}{% endblock %}

hello.js ♯viewのhtmlとjsファイルの間は、'document.getElementById'で受け渡し。
function myFunction() {
  var x = document.getElementById("mySelect").value;
  document.getElementById("demo").innerHTML = "You selected: " + x; #これで返せるところが嬉しい。
}

Output


3. Flask/Jinja2 <---> JSファイル間の変数の参照。

さて、本題のFlask/Jinja2 に渡されたリストをJavascriptで参照する件。


これは意外に簡単だった。 html内にJson形式で変数を定義して代入してあげれば良い。
この変数は、html内のスクリプトからも、外部ファイルのスクリプトからも参照できる。


以下、参考コード。

index.html

{% extends "layout.html" %}
{%block body%}

<h3> Show my current list from Python</h3>
<p id="current">{{my_list|tojson }}</p>

<script type="text/javascript">

current_list = {{ my_list|tojson }} ♯ Pythonファイルから受け取った変数を、jsで再定義。

function add2(){
document.getElementById("ex_list").innerHTML = "Your previous list on JS in this HTML is: " + current_list;

current_list.push(document.getElementById("new_wish").value);
document.getElementById("new_list").innerHTML = "Your new list on JS in this HTML is: " + current_list;
}
</script>

<h3>Select a new car from the list.</h3>
<select id="mySelect" onchange="myFunction()"> ♯form値のjsファイルへの送信。
  <option value="Audi">Audi
  <option value="BMW">BMW
  <option value="Mercedes">Mercedes
  <option value="Volvo">Volvo
</select>
<h3>When you select a new car, a function is triggered which outputs the value of the selected car.</h3>
<p id="demo"></p>
<span></span>
<p>Input new make you wish to add to the list:</p>
<input type="text" id="new_wish" name="new_wish" >
<input type="submit" value="add" onclick="addFunction(),add2()">
<p id="new"></p>
<hr>
<p id = "ex_list"></p>
<p id = "new_list"></p>
<hr>
<p id = "ex_list2"></p>
<p id = "new_list2"></p>
<script type="text/javascript" src="{{ url_for('static', filename='../static/hello.js') }}">
</script>
{%endblock%}

hello.js

function myFunction() {
  var x = document.getElementById("mySelect").value; ♯Form値の受取り
  document.getElementById("demo").innerHTML = "You selected: " + x;
}
function addFunction(){
 var new_make = document.getElementById("new_wish").value;
 document.getElementById("new").innerHTML = "You added from separate JS file: " + new_make;

 document.getElementById("ex_list2").innerHTML = "<li>"+"Your previous list from Separated JS file is: " + current_list + "</li>"; # !! Pythonで変数定義->Jinjaで再定義 -> JSファイルで受取り !!

#受け取った変数のJS.file内での処理
 current_list.push(document.getElementById("new_wish").value);


 document.getElementById("new_list2").innerHTML = "<li>"+"Your New list from Separated JS Fileis: " + current_list+ "</li>";
}
結果)



難点は、viewファイル上で変数にリストを代入した時に、内容がhtml上に表示されてしまうことかな?

そういう場合、「AJAXで、とか、Jqueryでとか書いてある。

これで、viewのhtmlに記述しないで、直接、Python <---> Javascript間で直接、変数の受け渡しが出来るようになる。 今は、そこまでやらないけど。


4. Python --> Flask/Jinja2 --> Javascript

test.py
from flask import Flask, render_template, request, redirect, url_for
import csv, random
app = Flask(__name__)
# randomの生成
def rando():
    quiz = []
    quiz2 = []
    rand_quiz =[]
    with open("sampleTest.csv","r", encoding='utf-8_sig') as f:
        reader = csv.reader(f)
        listreader=list(reader)
        for i in range(0,len(listreader)):
            if listreader[i][0]=='ALL' or 'CA':
                for j in range(1,6):
                    quiz.append(listreader[i][j])
                quiz2.append(quiz)
                quiz=[]
    rand_quiz=random.sample(quiz2,len(quiz2))
   
    return rand_quiz   <ーーこれは受け渡しに必要。ないと渡せない。

@app.route("/")
def index():
    rand_quiz = rando()
    return render_template('index.html',rand_quiz=rand_quiz)
if __name__ == '__main__':
    app.run(debug=True)

index.html

{% extends "layout.html" %}
{%block body%}

<h3> Show quiz in the list</h3>
{{rand_quiz}} <--①

<script>
rand_quiz = {{rand_quiz|tojson}} ♯python ファイルからのデータの受取り。
length = rand_quiz.length  ♯<script>内なので、javascriptの記述方式
</script>

<h3> Show First Quiz </h3>
Show Length : <p id="length"></p>      <--②
Specified List item<p id="quiz2"></p>    <--③
<script type="text/javascript" src="{{url_for('static', filename='../static/quiz.js')}} "></script>
{%endblock%}

quiz.js

window.onload=function quiz(){
document.getElementById("length").innerHTML= length  <--②
document.getElementById("quiz2").innerHTML= rand_quiz[0][0]  <--③ ♯jsで利用できる事の確認
}


結果)

Show quiz in the list[['山は?', 'Gut feeling', 'Mountain', 'River', '3'], ['川は?', 'Skin', 'River', 'Leather', '3'], ['犬は?', 'Dog', 'Cat', 'Tuna', '2'], ['空は?', 'Sky', 'Empty', 'Can', '2'], ['海は?', 'Octopus', 'Tuna', 'Sea', '4'], ['魚は?', 'Fish', 'Carmit', 'Dolphine', '2']]   <--①

Show First Quiz

Show Length :
<--②
Specified List item
山は? <--③



2 件のコメント: