よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

【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エラーが出たら手動でインストールする)


【前回までの参考】



ディレクトリ構成とファイルの中身

「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メソッドで送信。


  • inputタグformタグの中に書きます。
    • type属性 text : テキストボックスを設置。
      • name属性 : テキストボックスに入力された値が変数itemに入る。
    • type属性 submit : ボタンを設置。そのformタグの中に対してボタンが効く。
      • value属性 : ボタンに表示する文字。

result.html

google検索なら結果を表示するページにあたります。index.htmlformタグに設置したボタンが押されると入力値が表示されるようにします。
{{ 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」のどれか(全部同じ)にアクセスしますと、

f:id:chayarokurokuro:20220113211555j:plain
ホームページ

ルートにアクセスしたら表示されるページです。



f:id:chayarokurokuro:20220113211715j:plain
値を入力し、ボタンを押します
ボタンを押すと…↓↓↓



f:id:chayarokurokuro:20220113211817j:plain
resultページに入力した値が表示されました

直接「/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のredirecturl_forモジュールを使っていたり使わなかったりの違いは何か。
どのリクエストならどのページに飛ばすかの条件分岐などは、機能やページを増やすと複雑さも増す。Webアプリ作成動画を見ても「ここを変えたから次はここを書き換えて・・・」と行ったり来たりしています。エラーがどこで出ているのかも分かりにくい気がする。



ええいっ、ポンコツアプリを作り続けてりゃ覚える! がむばります(`・ω・´)