FlaskによるWebアプリ開発③~formタグでのデータのGET/POST送信

前回までにやったこと

前回はテンプレートエンジン「Jinja2」を使って、.pyファイルで定義した変数をhtml側に渡したり、Webページの表示内容を渡された変数の内容によって条件分岐させたり、for文を使ってリストを表示するなどの方法について解説しました。

前回の内容は.py(app.py)⇒html側(~~.html)にデータを渡していましたが、今回からは逆にhtml⇒.pyにデータを送る方法について紹介していきたいと思います。

リクエストとは

Webアプリケーションでは、ログインや入力フォームに代表されるようにユーザが入力した情報を処理に利用することがよくあります。このユーザーが入力した情報をサーバー側に送ることを一般的に「リクエスト」と言います。

ブラウザでWebページを閲覧する際には、サーバに「このファイルを見せてください」と要求(リクエスト)しており、サーバーがレスポンスとしてhtmlを返し、それをブラウザが人間に見やすい形で表示しています。

このリクエストの方法(メソッド)でよく使うものにGETPOSTがあり、Webアプリケーションを作るうえではこの2つについて理解していれば、ほとんどのものが作れるのでまずはこの2つを押さえておきましょう。

というわけで今日はflaskを使って「GET」と「POST」の流れや使い方について簡単に説明していきたいと思います。

GET/POSTの違い

GETやPOSTを利用すると、閲覧するファイルをリクエストすると同時に、フォームに入力された内容などのデータをサーバ(リクエストしたファイル)へ引き渡すことができます。GETとPOSTの特徴は以下となります。

<GETメソッド>
・HTML内で明示がない場合はGETとなる 例)ハイパーリンク(a要素)
・送信内容がURLに渡されると共に?以降が連想配列の「キー=値」として送られる(パラメータ)
・送信できるデータ情報量に制限がある

<POSTメソッド>

・入力した情報がURL上に表示されない

ちなみに、リクエストにおいて送信する内容のことを「リクエストパラメータ」と呼びます。そしてこの「リクエストパラメータ」がURLに見えるかどうかが「GET」と「POST」の大きな違いですね。

GETはhttp://url_for_taget/?key=value、のようにurlに直接データをねじ込めるので検索結果を表すページなどに使います。http://www.google.co.jp/search?q=python のように、GETを使ってリクエストパラメータをURLに含めると、検索結果の一覧が出ているページをブックマーク可能になります。

分かりやすい例としては、GoogleやAmazonの検索結果があります。ブラウザのURLのところを見ると訳の分からない文字列が大量に並んでいます。あれば元のURL+GETで付与した検索内容で作られたURLです。

そしてPOSTは会員登録などで名前・住所・パスワードみたいな秘匿性の高い情報を送信する際に、セキュリティの観点から利用します。まあPOSTが特段セキュリティが高いという訳でもなく、URLに送っているデータが丸だしになるGETよりはまだマシという程度で、SSL(https)などセキュリティ対策は別途必要です。

この2つの使い分けとしては、GETを使う明確なメリットがある場合以外は、基本的にPOSTを利用します。

flaskでGET処理を理解する

というわけで実際にflaskでGETとPOSTを理解していきましょう。まずは、以下のコードをapp.pyを作成してください。

めんどくさいという人はgitにコードを全部挙げているので、そちらをコピペなりダウンロードしてください

<app.py>

from flask import Flask, render_template
from flask import request

app = Flask(__name__)

# トップ画面
@app.route('/')
def index():
    return render_template('index.html')

# get処理の入力フォームを表示
@app.route("/request_get")
def get():
    return render_template('send_get.html')

# getでの入力情報処理
@app.route("/receive_get", methods=["GET"])
def receive_get():
    name = request.args["my_name"]
    if len(name) == 0:
        return "名前が未入力です"
    else:
        return 'あなたが入力した名前は' + str(name) + "です"

次に「templates」にsend_get.htmlを新規作成して以下のコードを記述しましょう。

<send_get.html>

<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>リクエストフォーム</title>
</head>
<body>
<h1>フォームに情報を入力してapp.py側に送信する</h1>
<form method="get" action="receive_get">
<label>名前: <input type="text" name="my_name"></label>
<input type="submit" value="送信する">
</form>
</body>
</html>

app.pyのあるディレクトリに移動して$python app.pyでアプリを起動してブラウザからhttp:localhost:5000/request_getにアクセスしてみましょう。

名前を入力し[送信する]ボタンをクリックするとページが遷移し、入力した名前が表示されます。名前を入力せずに[送信する]を推すと名前を入力してくださいという警告がでます。

一応処理の流れを説明すると、まず注目したいのは@app.route("/request_get")~の部分で入力フォームのsend_get.htmlを表示しています。

そして、ここで名前を入力し送信ボタンをクリックすると、send_get.htmlのフォームタグには<form method=”get” action=”/receive_get”>と書いてあるため、/receive_getというURLにアクセスします。

ちなみにここで使われている<form>タグはhtmlからサーバー側に情報を送信したい時に使うタグで、フォームで入力した情報を送信すると、共にその送信に使うメソッド(GET/POST)の指定と送信先のURLを指定できます。

今回はGETで送信したいのでmethod="get"としています。そして、action="receive_get"と記述することで、入力データの送信先URLを[/receive_get]にすると指定しています。

そして、再びapp.py側に処理が戻って、@app.route("/receive_get", methods=["GET"])~の部分が実行されます。

先ほど入力フォームに入力した情報はname=request.args["my_name"]でサーバー側で受け取っています。

Flaskの関数の1つである「request」に用意されているrequest.args()は連想配列(キーが設定に合わせて自動生成される配列)で、配列のキーはsend_get.htmlの入力フォーム(<form>~</form>)で input要素のname属性に指定した名前(今回だとname=”my_name”)になります.

なので、request.args['my_name']とすると、html側でGETで送った入力情報をサーバー側(app.py)で取得することができます。格納されているデータはrequest_get.htmlの入力フォーム部分でユーザがテキストボックスに入力した値となります。

ここでは試しに「taro」と入力してみます。

すると、app.pyの@app.route("/receive_get", methods=["GET"])のreceive_get()関数が実行されます。今回はtaroと入力したので、request.args['my_name']には、’taro’というデータが入っており、変数nameにはtaroという文字型データが代入されています。

そして、その下のif文でnameの文字列はの長さは0ではないので、else以下が実行され、returnで「’あなたが入力した名前は’+str(name)+”です”」の部分が返されることで、html側には以下のように表示されます。

そして、後述するPOSTとの違いとして注目すべきはURLの部分ですね。URLがhttp://127.0.0.1:5000/receive_get?my_name=taroという風になっています。

これはhttpメソッド(リクエスト方式)にGETを使用していると、URLに?keyvalue=〇〇という形で送信した情報が見えます。

<form>タグについて

<form>タグは、入力・送信フォームを作る際に使用します。 <form>~</form>の間に、 <input>・ <select>・ <textarea>等のタグで、 一行テキストボックス・サブミットボタン・ラジオボタン・チェックボックス・セレクトボックス・テキストボックス等のフォーム部品を配置することができます

フォームに入力されたデータは、送信ボタンを押すことでサーバー側へ送信されます。今回の場合だと、Pythonとflaskで書かれたサーバー側の管理ファイルである app.py に送信されます。

その際の送信先URLはaction属性で、データの送信方法はmethod属性で、送信するデータの形式はenctype属性でそれぞれ指定します。

ウェブサーバーへ送信されたデータのプログラム処理は、 HTMLやCSSではなく、PHPやPython・Rubyなどで処理します。

初期値はmethod="get"です。 getの場合だとフォーム入力された内容は、action属性で指定したURLの後ろにクエスチョンマーク( ? )を付けて、それ以降続くにクエリとして送信先ページに渡されます。

これは先ほどのhttp://127.0.0.1:5000/receive_get?my_name=taroでも分かりますね。一般的なブラウザではURLの長さに制限があるため、長すぎるデータは途中で切れてしまうので注意が必要です。

GETは短めのキーワードや番号などを送信するのに適した送信方法であり、長い文章などを送信するのには向いていません。 “get”というのは「クエリ付きURLの情報を“取得する”」という意味です。

ですがここで、method="post"を指定するとURLの後ろに付くクエリとしてではなく、送信内容自体が本文(本体)として送信されます。 POSTの場合だと入力内容がURLに表示されることはなく、かなり長い文章も送信することができます。 “post”というのは「フォームの内容を送信先ページに“送る”」という意味です。

他にも細かい指定はありますが、これは本筋ではないのでこの辺にしておきます。<form>タグについての詳しいことは↓に書かれています。

参照:http://www.htmq.com/html5/form.shtml

flaskでPOST処理を理解する

次はPOST処理をFlaskでやっていきます。app.pyに以下のコードを追加して、「templates」にsend_post.htmlを新しく作ってください。

<app.py>

# post処理の入力フォームを表示
@app.route("/request_post", methods=["GET"])
def post_sample():
    return render_template('send_post.html')

# postでの入力情報処理
@app.route("/request_post", methods=["POST"])
def post_action():
    if "gender" in request.form.keys():
        gender = request.form["gender"]
        if gender == "男":
            sex = '男性'
        elif gender == "女":
            sex = "女性"
    else:
        sex = '性別不明'
    if 'age' in request.form.keys():
        age_range = request.form['age']
    else:
        age_range = '年齢不詳'
    return f'あなたは{sex}で{age_range}です。'

<send_post.html>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>リクエスト使用例</title>
</head>
<body>
    <h2>ユーザー情報を入力してください</h2>
    <form method="post">
        <input type="radio" name="gender" value="男" {{checked1}}>男
        <input type="radio" name="gender" value="女" {{checked2}}>女
        <input type="submit" value="送信">
<p></p>
<!-- セレクトボックス -->
<select name="age">
<option value="">選択してください</option>
<option value="20歳未満">20歳未満</option>
<option value="20-29歳">20-29歳</option>
<option value="30-39歳">30-39歳</option>
<option value="40-49歳">40-49歳</option>
<option value="50-59歳">50-59歳</option>
<option value="60-69歳">60-69歳</option>
<option value="70-79歳">70-79歳</option>
<option value="80歳以上">80歳以上</option>
</select>
</form>
<p></p>
</body>
</html>

POSTでも、先ほどのGETと同じように、ラジオボタンのチェックした値を取得し表示しています。GETとは違ってURLの後ろにリクエストパラメーターは付与されておらず、送信した後のURLに?=~~みたいなパラメータが付いていません。

GETやPOSTで入力情報を送ることができるのはテキストボックスだけでなく、今回作成したラジオボタン、セレクトボックスなど、ユーザが選択や入力可能な情報はFlaskでだとGETリクエストの場合ならrequest.args()、POSTリクエストの場合ならrequest.form()で受け取ることが可能です。

なおテキストボックス<input type=”text”>の場合は、ユーザが入力した値が送られてきましたが、ラジオボタンやセレクトボックスの場合、value=””に指定した値が、request.argsまたはrequest.formに送られてきます。※セレクトボックスはvalueを指定しなかった場合、表示されている値が送信されます。

今回の場合だと

<input type="radio" name="gender" value="男" >男
<input type="radio" name="gender" value="女" >女

なので、app.pyのrequest.form["gender"]に送られるのはvalue="男" 、value="女"のどちらかになります。

そして、サーバー側(app.py)でif文の条件分岐で、変数に男性か女性がどちらを出力するかを決めています。また入力せずに送信した場合はelse以下の処理で性別不明と返すようにしています。その下のageの部分も性別と同じような流れになっています。

まとめ

以上がGETとPOSTの違いと、それをFlaskにおいて実装する方法です。とりあえずGET/POSTと<form>タグを理解すると、外側はそれっぽいWebアプリが作れるようになります。

<app.py>(python3.6以上で動作可能)

from flask import Flask, render_template
from flask import request

app = Flask(__name__)

# トップ画面
@app.route('/')
def index():
    return render_template('index.html')

# get処理の入力フォームを表示
@app.route("/request_get")
def get():
    return render_template('send_get.html')

# getでの入力情報処理
@app.route("/receive_get", methods=["GET"])
def receive_get():
    name = request.args["my_name"]
    if len(name) == 0:
        return "名前が未入力です"
    else:
        return 'あなたが入力した名前は' + str(name) + "です"

# post処理の入力フォームを表示
@app.route("/request_post", methods=["GET"])
def post_sample():
    return render_template('send_post.html')

# postでの入力情報処理
@app.route("/request_post", methods=["POST"])
def post_action():
    if "gender" in request.form.keys():
        gender = request.form["gender"]
        if gender == "男":
            sex = '男性'
        elif gender == "女":
            sex = "女性"
    else:
        sex = '性別不明'

    if 'age' in request.form.keys():
        age_range = request.form['age']
    else:
        age_range = '年齢不詳'
    return f'あなたは{sex}で{age_range}です。'

# テスト環境起動
app.run(debug=True)

参照:https://github.com/beginerSE/flask_form

この記事で作ったサンプルアプリケーションは私のgitにアップロードしているので、そちらをダウンロードして動かしていただけると、理解が深まるかと思います。

今回は単に<form>タグで入力された情報をhtml上にそのまま表示させるだけでしたが、ユーザー登録などでユーザー側が送信した情報を保管するためには、データベースとの接続が必要になってきます。

というわけで次回からはWEBフレームワークのflaskとsqliteというデータベースを連結させて、html側から入力した情報をデータベースに記録したり、データベースに保管されている情報をHTMLに送る方法について解説していきます。

この記事の続き→flaskによるWebアプリ開発④~SQLAlchemyでPythonとデータベースと連携させる

関連記事:Pythonでデータベース(DB)を作成・操作できる「sqlite3」の使い方

関連記事:【Python】スクレイピングした価格データをデータベース(DB)に保存

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で



「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」

「エンジニアとして若いうちから高収入を得たい」



という強い気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする

   侍エンジニア塾       
侍エンジニアの無料体験レッスンを予約する -->