【Flask】送信ボタンを押してテキスト送受信を行う
今回は、「入力欄」「ボタン」だけを設置したシンプルなページを作ります。また、ボタンを押して入力値をFlask側に渡し、別のページに表示させます。
googleのホームページは「入力欄」と「検索ボタン」だけのシンプルなものです。で、キーワードを書きボタンを押すと、検索結果のページに飛ばされます。 しかしシンプルといいながらも、構造は結構複雑です。送信ボタンを押して値を表示させるだけですが、Webアプリ作成初心者にとっての第一関門かなと思います。エラー連発します。
目次
実行環境
- Windows10 Home
- Anaconda 4.11.0
- Python 3.9.7
- VSCode 1.63.2
- 外部ライブラリ
- Flask 2.0.2
- colorama(Windowsの場合、Flask実行時にNo Moduleエラーが出たら手動でインストールする)
【前回までの参考】
- 【WSL/Anaconda/Flask】仮想環境の作成とFlaskのインストール、簡単なWebアプリ作成 - よちよちpython
- 【Windows限定?】Flask実行時の'colorama' No Module のエラー対策 - よちよちpython
- 【Flask】render_templateでpyファイルとhtmlファイルを分ける - よちよちpython
ディレクトリ構成とファイルの中身
「flask_sample」というディレクトリで作業しております。
htmlファイルはFlaskの既定である「templates」フォルダを作ってその中に入れておきます。別のフォルダ名だとエラーが出たりします。
flask_sample/ ├── app.py └── templates ├── base.html ├── index.html └── result.html 1 directory, 4 files
base.html
htmlファイルでメタ情報が書かれた部分(bodyタグ
以外)は大体どのファイルでも共通しているので取り出して「base.html」という名前で別ファイルにします。
以下はVSCodeのEmmet「! + tabキー
」で出力されたもの。
※ titleタグ
とbodyタグ
の中に波カッコ{}
の部分は追加。
詳しいことは FlaskかDjangoのテンプレートエンジンの使い方 で検索ください。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- タイトル --> <title>Flaskサンプル-{% block title %}{% endblock %}</title> </head> <!-- コンテンツ内容 --> <body> {% block content %} {% endblock %} </body> </html>
index.html
ホームページです。「テキストボックス入力欄」と「ボタン」を設置します。
{% extends 'base.html' %} {% block title %}ホームページ{% endblock %} {% block content %} <form action="/result" method="POST"> <p>検索:<input type="text" name="item"></p> <p><input type="submit" value="検索"></p> </form> {% endblock %}
この場合、ボタンを押すとtextボックス
に入力されたname属性=item
の値が、POSTメソッド
で/result
ページに送信されます。
formタグ
- action属性 : ボタンを押すと値が
/result
ページに送信。 - method属性 : 今回はPOSTメソッドで送信。
- action属性 : ボタンを押すと値が
inputタグ
:formタグ
の中に書きます。- type属性 text : テキストボックスを設置。
- name属性 : テキストボックスに入力された値が変数itemに入る。
- type属性 submit : ボタンを設置。そのformタグの中に対してボタンが効く。
- value属性 : ボタンに表示する文字。
- type属性 text : テキストボックスを設置。
result.html
google検索なら結果を表示するページにあたります。index.html
のformタグ
に設置したボタンが押されると入力値が表示されるようにします。
{{ txt }}
に入力値が入るようにしました。
{% extends 'base.html' %} <!-- タイトル表示 --> {% block title %}入力の表示{% endblock %} <!-- コンテンツ内容の表示 --> {% block content %} {{ txt }} {% endblock %}
app.py
ブラウザから送信された値をサーバ側が受け取るにはrequest
モジュールをインポートする必要があります。
入力値を表示する/result
ページの処理を追加します。
from flask import Flask, render_template, request app = Flask(__name__) # ホームページ @app.route('/') def index(): return render_template('index.html') # 入力値の表示ページ @app.route('/result', methods=['GET', 'POST']) def result(): # index.htmlのinputタグ内にあるname属性itemを取得し、textに格納した text = request.form.get('item') # もしPOSTメソッドならresult.htmlに値textと一緒に飛ばす if request.method == 'POST': return render_template('result.html', txt = text) # POSTメソッド以外なら、index.htmlに飛ばす else: return render_template('index.html') if __name__=='__main__': app.run(debug=True)
もし/result
ページに直接アクセスすると自動的にGETメソッド
のリクエストが送られます。するとelse
で書いたようにindex.html
に飛ばすようにしています。
実行
ターミナルで実行します。
PS > python app.py
ブラウザで「127.0.0.1:5000」「http://127.0.0.1:5000」「localhost:5000」のどれか(全部同じ)にアクセスしますと、
ルートにアクセスしたら表示されるページです。
ボタンを押すと…↓↓↓
直接「/result
」ページにアクセスするとホームページが表示されます。
おわりに
他の言語によるWebアプリ開発経験がなく、html/cssも未学習のような人(私)にとっては、ハマリどころがたくさんあります。「Pythonは学習コストが低く」「FlaskはシンプルなWebフレームワーク」だとしても、それ以外の学習コストが高い。WebやWebアプリはかなり仕組みが複雑かと思います。
「クライアント(PC・ブラウザ)
からサーバ(サーバ・CGI)
へGETやPOSTリクエストがhttp通信で云々」、みたいなことはWebの仕組みを知っているかどうかです。知りまへんがな。『古事記』に 『Python 入門書』に書かれていないし( ^ω^)・・・
最初、「POSTはブラウザのボタンを押したときの信号で(POSTされ)、GETはサーバが受け取る(GET)信号」かと勘違いしていました。しかし両方とも主語はブラウザのようです。ブラウザがGETリクエストもPOSTリクエストも行う。
次のポイント。ボタンを押して送信される値は、inputタグ
のname属性
が送られる、ということ。
id属性
やclass属性
やname属性
やvalue属性
が同じ変数で書かれているようなサンプルコードを参考に勉強すると、どの値が送信されているのか分かりません。しかもたぶん当たり前すぎて説明されていない。
次、GETやPOSTで送られてきた値をpython側で受信するとき。request.args['name属性']
、request.form['name属性']
、request.form.get('name属性')
など、受け方が複数ある。で、ブログなどのサンプルでは大体そこの説明がされていません。この部分はエラーが出まくる。
ほか、python側でブラウザからのリクエストに対しての処理方法。GETとPOSTの違いによる条件分岐などの部分。
Flaskのredirect
やurl_for
モジュールを使っていたり使わなかったりの違いは何か。
どのリクエストならどのページに飛ばすかの条件分岐などは、機能やページを増やすと複雑さも増す。Webアプリ作成動画を見ても「ここを変えたから次はここを書き換えて・・・」と行ったり来たりしています。エラーがどこで出ているのかも分かりにくい気がする。
ええいっ、ポンコツアプリを作り続けてりゃ覚える! がむばります(`・ω・´)