Flaskで投稿フォームを作ってみましょう。投稿フォームはWebアプリケーションでよく使われるものの1つで、実装にはFlaskの知識に加えてHTMLとHTTPメソッドの知識が必要となります。
目次
WebブラウザとWebサーバー間のHTTP通信
Webページは、Webブラウザからのリクエストに応じてWebサーバーがレスポンスを返し、その内容をブラウザが表示しています。このWebブラウザとWebサーバーの通信に使われているのがHTTPメソッドです。
WebブラウザとWebサーバー間の通信には主にGETメソッドとPOSTメソッドというHTTPメソッドを使います。
Flaskでは特に何も指定しないとGETメソッドに対応した処理となりますが、ユーザーからデータを受け取る場合はGETメソッドでは不都合な場合もあるため、フォームの内容を送受信する際には使用するメソッドを指定するのが一般的です。
投稿フォームの作成と表示
flask-tutorialディレクトリの下に hello.py を用意し、次のように記述します。
from flask import Flask, render_template app = Flask(__name__) # ルートディレクトリのURLをトリガーに @app.route("/") def show(): return render_template("form.html") # form.htmlファイルをテンプレートとして呼び出す
トップページ(ルートディレクトリのURL)にはアクセスすると form.html をテンプレートファイルとして呼び出すよう記述しました。
次はこの form.htmlを作りましょう。templatesディレクトリの下に作成します。
{%extends "layout.html" %} <!-- 共通テンプレートの呼び出し --> {% block content %} <h1>フォーム</h1> <form action="/result" method="post"><!-- データの送信先アドレスと送信する際に使用するHTTPメソッド --> <label for="article">投稿</label> <input type="text" name="article"><!-- 投稿するデータのname属性を指定--> <p></p> <label for="article">名前</label> <input type="text" name="name"><!-- 投稿するデータのname属性を指定--> <button type="submit">送信する</button><!-- 送信ボタン --> </form> <p>{{ article }} {{ name }}</p> {% endblock %}
5行目でデータの送信先(/result)と、フォームに入力した内容をPOSTメソッドで送信するよう記述。
あとはHTMLで入力フォームを作成し、13行目でそれらのデータをpタグで囲んで出力するよう記述しています。
では、次はデータの送信先である /result の表示内容を作成しましょう。
hello.py に次のように追記します。
from flask import Flask, request, render_template # requestを追加 app = Flask(__name__) # ルートディレクトリのURLをトリガーに @app.route("/") def show(): return render_template("form.html") # /resultをトリガーに @app.route("/result", methods=["POST"]) # POSTメソッドに対応した処理 def result(): article = request.form["article"] # フォームからデータを取り出す name = request.form["name"] # フォームからデータを取り出す return render_template("form.html", article = article, name = name)
フォームのデータを取り出して変数に割り当てるには import に request を追加し、次のように記述します。
request.form[“フォームのテキストボックスのname属性”]
13,14行目でフォームの article と name を取り出して、それぞれ article と name という変数に代入しています。
そして15行目でこれらの変数を form.html の引数として渡して表示するよう記述しています。
ではflaskコマンドを使ってアプリケーションを実行し、ブラウザで確認してみましょう。
トップページ(http://127.0.0.1:5000/)にアクセスします。
このように「投稿」「名前」2つの入力欄がある投稿フォームを作成できました。
実際にデータを入力して送信ボタンを押してみましょう。
入力した内容がpタグで囲まれて表示されました。
GETメソッドで送受信する
先ほどはPOSTメソッドでフォームのデータを送信していましたが、GETメソッドでの送信も試してみましょう。
hello.py に次のように記述します。
from flask import Flask, request, render_template app = Flask(__name__) # ルートディレクトリのURLをトリガーに @app.route("/") def show(): return render_template("form.html") # /resultをトリガーに @app.route("/result", methods=["GET", "POST"]) # GETとPOSTメソッドに対応した処理 def result(): # HTTPメソッドがPOSTの場合 if request.method == "POST": article = request.form["article"] name = request.form["name"] # それ以外の時(GETの時) else: article = request.args.get("article") # フォームからデータを取り出す name = request.args.get("article") # フォームからデータを取り出す return render_template("form.html", article = article, name = name)
11行目でrouteデコレータのmethods引数に”GET”を追加し、if文でPOSTメソッドの場合とそれ以外の場合で処理を変えています。
GETメソッドでフォームからデータを取り出す場合は次のように記述します。
article = request.args.get(“name属性”)
先のコードでは19,20行目がGETメソッドの場合にフォームからデータを取り出す記述です。
次に、フォームからデータを送信する際の通信方法をGETメソッドに変えましょう。
form.html を次のように変更します。
{%extends "layout.html" %} {% block content %} <h1>フォーム</h1> <form action="/result" method="get"><!-- データの送信に使用するHTTPメソッドをgetに変更 --> <label for="article">投稿</label> <input type="text" name="article"> <p></p> <label for="article">名前</label> <input type="text" name="name"> <button type="submit">送信する</button> </form> <p>{{ article }} {{ name }}</p> {% endblock %}
ではflaskコマンドを使ってアプリケーションを実行し、ブラウザで確認してみましょう。
トップページ(http://127.0.0.1:5000/)にアクセスします。
フォームの表示自体は変わりません。
ではデータを入力して送信ボタンを押してみましょう。
画面の表示自体は変わりませんが、ブラウザのアドレスを見るとformで送信したデータが含まれています。
このようにGETメソッドではページのアドレス(URL)にユーザーが送信したデータが含まれてしまうため、他人からデータが見られやすい状態になります。
検索フォームなどではGETメソッドが採用されやすいのですが、パスワードの送信を行うログイン画面などでは必ずPOSTメソッドを使用しましょう。