概要
flaskを使用した基本的なGET/POSTリクエストの方法についてまとめた。
それぞれの通信にて、画面(HTML)とサーバー(Pythonファイル)間でどのようにデータを受け渡すのかを扱う。
尚、GET/POSTとは何か、またその使い分けについては扱わない。
概要 flaskモジュールを使用して簡易的なサーバーをローカルに作成したので、その方法についてまとめる。 flaskとは、PythonのWEBアプリケーションフレームワークの一つ。 flaskの使用方法 ライブラ[…]
概要 Jinjaテンプレートを使用して、サーバーからの値をHTMLに埋め込む方法についてまとめた。 テンプレートとは、プログラムからデータを渡して動的に文章を作成するためのひながた。 Jinjaテンプレートでは、値を埋め込むだけで[…]
GETの場合
アンカータグを使用してパラメータを送る
画面遷移
1番~3番がアンカータグで囲まれたリンクになっている。
リンクのどれかを押下すると、GETリクエストにより指定のURLへ送信する。
その際に、パラメータも一緒にサーバー側へ渡す。
サーバー側ではGETリクエストにより渡されたパラメータを取得し、結果画面にデータを返却する。
画面側
<div style="outline: 1px solid black; width:50%; padding: 0.5rem">
<h5>リンク送信(クエリパラメータ)</h5>
<p>IDを選択してください。</p>
<ul>
<li><a href="/result?id_key=1">1番</a>:冷蔵庫</li>
<li><a href="/result?id_key=2">2番</a>:洗濯機</li>
<li><a href="/result?id_key=3">3番</a>:テレビ</li>
</ul>
</div>
アンカータグのURLに、以下の形式でURLを設定する。
「?」以降の「変数名=値」の部分をクエリパラメータやクエリストリングとよぶ。
この形式で記述すると、GETリクエストでサーバー側にパラメータを送信できる。
尚、複数のクエリパラメータを送りたい場合、「&」で区切ればOK。
上記の場合、id_keyという変数名にそれぞれ1~3の値を設定している。
サーバー側
@app.route("/result")
def result():
""" GETのクエリパラメータを受け取る """
id_key = request.args.get("id_key", "")
ID_MAP = {'1': '冷蔵庫', '2': '洗濯機', '3': 'テレビ'}
return render_template("/sub/result.html", id_result=ID_MAP[id_key])
request.argsに辞書型の形式でクエリパラメータが格納される。
そのため、以下のように記述することでクエリパラメータを取得できる。
id_key = request.args.get("id_key", "")
request.args[“変数名”]と記述しても取得は可能だが、取得できない場合はKeyErrorになる。
KeyErrorを回避するために、上記のようにgetメソッドを使用して、パラメータを取得できない場合は空文字とするなどの対応が必要。
上記の場合、”id_key”というキーで値を取得できた場合、id_key変数に格納する。
取得できない場合、空文字をid_key変数に格納する。
フォームを使用してパラメータを送る
画面遷移
サーバー側ではGETリクエストにより渡されたパラメータを取得し、結果画面にデータを返却する。
画面側
<h5>フォーム送信</h5>
<div style="outline: 1px solid black; width:50%; padding: 0.5rem">
<form method="get" action="/result_2">
<p>名前:<input type="text" name="name" size="40"></p>
<button type="submit">送信</button>
</form>
</div>
formタグのmethod属性に「get」を設定することで、GETリクエストにて送信できる。
action属性にはリクエスト送信先のURLを設定する。
クエリパラメータとして送信するパラメータは、form内のテキストボックス。
name属性に定義したnameが変数名になる。
サーバー側
@app.route("/result_2")
def result_2():
""" GETのクエリパラメータを受け取るその2 """
your_name = request.args.get("name", "")
return render_template("/sub/result.html", name=your_name)
アンカータグの時と同じように、request.argsに辞書型の形式でクエリパラメータが格納される。
getメソッドに変数名を指定して取得する。
POSTの場合
フォームを使用してパラメータを送る
画面遷移
以下のform部品を入力or設定して送信ボタンを押下する。
・テキストボックス
・テキストエリア
・セレクトボックス
・チェックボックス
・ラジオボタン
サーバー側で送られてきたすべてのform部品から画面入力値を取得し、画面にそのデータを返却する。
画面側
<div style="outline: 1px solid black; width:50%; padding: 0.5rem">
<form action="/result_3" method="post">
<label for="fname">名前(テキストボックス):</label><br>
<input type="text" id="fname" name="fname"><br><br>
<label for="description">説明(テキストエリア):</label><br>
<textarea id="description" name="description" rows="4" cols="50"></textarea><br><br>
<label for="cars">車メーカー(セレクトボックス):</label><br>
<select id="cars" name="cars">
<option value="1">トヨタ</option>
<option value="2">ホンダ</option>
<option value="3">ダイハツ</option>
<option value="4">スズキ</option>
</select><br><br>
<p>ニュースレターを購読(チェックボックス):</p>
<input type="checkbox" id="subscribe1" name="subscribe1" value="news1">
<label for="subscribe1">ニュース1</label><br>
<input type="checkbox" id="subscribe2" name="subscribe2" value="news2">
<label for="subscribe2">ニュース2</label><br>
<input type="checkbox" id="subscribe3" name="subscribe3" value="news3">
<label for="subscribe3">ニュース3</label><br><br>
<p>性別(ラジオボタン):</p>
<input type="radio" id="male" name="gender" value="male">
<label for="male">男性</label><br>
<input type="radio" id="female" name="gender" value="female">
<label for="female">女性</label><br><br>
<input type="submit" value="送信">
</form>
</div>
formタグのmethod属性に「post」を設定することで、POSTリクエストにより送信できる。
action属性にはリクエスト送信先のURLを設定する。
サーバー側
@app.route("/result_3", methods = ["POST"])
def result_3():
""" POSTのパラメータを受け取る """
ctx = {}
# テキストボックス
ctx["名前"] = request.form["fname"]
# テキストエリア
ctx["説明"] = request.form.get("description", "入力なし")
# セレクトボックス
ctx["車"] = request.form.get("cars", "入力なし")
# チェックボックス
ctx["ニュース1"] = request.form.get("subscribe1", "入力なし")
ctx["ニュース2"] = request.form.get("subscribe2", "入力なし")
ctx["ニュース3"] = request.form.get("subscribe3", "入力なし")
# ラジオボタン
ctx["性別"] = request.form.get("gender", "入力なし")
return render_template("/sub/result.html", ctx=ctx)
POSTリクエストでパラメータを取得する際には、URLのルーティングする箇所に以下の設定を行う。
上記を設定をしないと、サーバー側でリクエストを拒否してしまう。
また、パラメータを取得する場合はrequest.formに辞書形式で格納されている。
request.form[“辞書キー”]としても取得は可能だが、取得できない場合はKeyErrorになる。
そのため、getメソッドを使用する方がいい。
ただし、テキストボックスとテキストエリアについてはrequest.form[“辞書キー”]で値を取得できていなくてもKeyErrorが発生しなかった。
その他
url_for()
url_forメソッドをHTMLテンプレート側で使用することで、サーバー側と疎通できる。
これまでのGET/POSTリクエストのHTML側での記述を、url_forメソッドで書き換えが可能。
また、動的なURL作成にも対応できる。
使い方
アンカータグ
<li><a href="/result?id_key=3">3番</a>:テレビ</li>
<li><a href="{{ url_for('result', id_key=3) }}">3番</a>:テレビ</li>
url_for()の第一引数にはサーバー側のメソッドを指定する。
第二引数以降にはクエリパラメータを設定可能。
フォーム
<form action="/result_3" method="post">
<form action="{{ url_for('result_3') }}" method="post">
url_for()の引数にサーバー側のメソッドを指定する。
動的なURLを作成する
画面遷移
処理の流れ
サーバー側からリストを渡して、画面側で動的に一覧データを表示する。
その際に、ID項目に対してアンカータグを設定する。
アンカータグには動的に取得したIDを設定する。
リンクを押下すると、サーバー側で取得したIDをもとに該当するデータを結果画面に返す。
一般的なECサイトなどで商品一覧をDBから検索して表示した後に、個別の詳細画面を表示するような動き。
トップ画面表示処理
画面側
<table>
<tr>
<th>ID</th>
<th>名前</th>
<th>部活</th>
<th>趣味</th>
</tr>
{% for s in students %}
<tr>
<td><a href="{{ url_for('result', s_id=s.id) }}">{{ s.id }}</a></td>
<td>{{ s.name }}</td>
<td>{{ s.bukatu }}</td>
<td>{{ s.hobby }}</td>
</tr>
{% endfor %}
</table>
{% for s in students %}
<tr>
<td><a href="{{ url_for('result', s_id=s.id) }}">{{ s.id }}</a></td>
<td>{{ s.name }}</td>
<td>{{ s.bukatu }}</td>
<td>{{ s.hobby }}</td>
</tr>
{% endfor %}
画面側ではstudentsリストを受け取り、Studentオブジェクトをループする。
url_for関数のクエリパラメータにs_idという変数でStudentオブジェクトのid属性を設定する。
これにより、サーバー側へs_idという変数でパラメータを動的に設定して送信する。
サーバー側
# 学生情報
class Student:
def __init__(self, id, name, bukatu, hobby):
self.id = id
self.name = name
self.bukatu = bukatu
self.hobby = hobby
# 学生情報リスト
STUDENTS = [
Student(1, "山田", "野球部", "映画鑑賞"),
Student(2, "佐藤", "サッカー部", "お笑い鑑賞"),
Student(3, "園田", "茶道部", "手芸")
]
@app.route("/")
def index():
""" トップ画面表示 """
return render_template("/sub2/index.html", students=STUDENTS)
初期画面を表示する際に、Studentクラスのリストを画面側に渡している。
id、name、bukatu、hobby属性を保持している。
リンク押下後、結果画面表示処理
画面側
<body>
<p>ID: {{ student.id }}</p>
<p>名前: {{ student.name }}</p>
<p>部活: {{ student.bukatu }}</p>
<p>趣味: {{ student.hobby }}</p>
<p><a href="/">戻る</a></p>
</body>
サーバー側から渡されたStudentクラスの情報を表示する。
サーバー側
@app.route("/res/<s_id>")
def result(s_id):
for s in STUDENTS:
if s.id == int(s_id):
res = s
return render_template("/sub2/result.html", student=res)
動的なクエリパラメータを受け取る場合、以下のように記述する。
@app.route(“/res/<s_id>“)
def result(s_id):
for s in STUDENTS:
if s.id == int(s_id):
(略)
上記赤文字箇所の変数名は、HTMLテンプレート側のurl_forメソッドにて指定したクエリパラメータの変数名を設定する。
上記のように記述することで、画面側から動的に設定したパラメータを取得することができる。