はじめての Flask #2 ~POSTを受け取ろう~

[前回: ~はじめてのウェブアプリ~](https://qiita.com/nagataaaas/items/d249c3905d41137cd510)

今回は、ページからのPOSTを受け取って、動的にページを作成しようと思います。

ここを理解すれば、フォームもあらかた理解できるでしょう。

#formを作ろう！

Flaskでページを出力するにはいくつか方法があり、

- return で文字列(html)を返す
- render_template でtemplatesフォルダー内のhtmlファイルを返す

の二つが主な手法です。今回は少ないコードで済むので、1番目を採用しましょう。

```python
return "html内部"
```
という風に返します。

##ここで少しhtmlのお勉強
htmlでフォームを表現するには、**\<form\>**タグを使います。

また、このタグには**action**と**method**パラメータをつけましょう。(methodは必須ではありません)

actionタグではデータを送信する先を指定し、methodでは送り方を決めます。methodには2種類あり、それぞれ**"GET"**と**"POST"**です。
GETはurlに直接データをねじ込みます。

```
http://url_for_taget/?key=value
```

の様になります。

ですが、POSTではURLからはデータの内容は分かりません。直接見れない形でデータが送られるからです。この解析には、fiddlerなどのツールを用います。

今回は、これを使います。

また、フォームの中には送るデータを入力させなければいけません。今回は、**inputフィールド**を使用しましょう。

また、flask側でpostを解析するためにinputに**name**をつけなければいけませんので、それも忘れずに！

#実装

現段階をまとめると

```python
from flask import *

app = Flask(__name__)


@app.route("/")
def odd_even():
        return """
        下に整数を入力してください。奇数か偶数か判定します
        <form action="/" method="POST">
        <input name="num"></input>
        </form>"""

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8888, threaded=True)
```

の様になります。

では、データが送られてきた後の動作を実装しましょう！

まず、**POSTを受け取れるように変更**しましょう。

```python
from flask import *

app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def odd_even():
        return """
        下に整数を入力してください。奇数か偶数か判定します
        <form action="/" method="POST">
        <input name="num"></input>
        </form>"""

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8888, threaded=True)
```

app.route に methodsが増えましたね。これで、POSTとGETの二つのメソッドを許可できました。標準ではGETのみになっています。

これをしないでPOSTすると、**"そんな方式は受け取れないよ！"とエラーを吐かれ**ます

次に、GETの時(普通に接続されたとき)とPOSTの時(データを送られたとき)の動作を分けて、POSTの時の動作を付け加えましょう！

```python
from flask import *

app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def odd_even():
    if request.method == "GET":
        return """
        下に整数を入力してください。奇数か偶数か判定します
        <form action="/" method="POST">
        <input name="num"></input>
        </form>"""
    else:
        return """
        {}は{}です！
        <form action="/" method="POST">
        <input name="num"></input>
        </form>""".format(str(request.form["num"]), ["偶数", "奇数"][int(request.form["num"]) % 2])

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8888, threaded=True)
```

Flaskには、ページへの接続方式を探知する機能があります。

それは、**request.method**です。
GETかPOSTを返します。

また、formのデータをうけとるのに**request.form**を使えます。ディクショナリで、key(name)とvalue(データ)をくれます。

ですので、request.form["num"]とすると、formの中のnameがnumのデータを取り出せます。
ただ、inputで得られるデータは文字列ですので、気を付けなければいけません。

数字でない文字列を与えられたときのエラーを出力するページも作りましょう

```python
from flask import *

app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def odd_even():
    if request.method == "GET":
        return """
        下に整数を入力してください。奇数か偶数か判定します
        <form action="/" method="POST">
        <input name="num"></input>
        </form>"""
    else:
        try:
            return """
            {}は{}です！
            <form action="/" method="POST">
            <input name="num"></input>
            </form>""".format(str(request.form["num"]), ["偶数", "奇数"][int(request.form["num"]) % 2])
        except:
            return """
                    有効な数字ではありません！入力しなおしてください。
                    <form action="/" method="POST">
                    <input name="num"></input>
                    </form>"""


if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8888, threaded=True)
```

try-exceptで十分でしょう。

実行してみてください。これで、奇数偶数判定プログラムができましたね！

少し変えるだけで、BMIを計算したり、素数判定をしたり、数あてゲームをしたり…　いろいろできそうですよね！

次回は[htmlファイルとjinja2を使ってrenderしてみましょう！](https://qiita.com/nagataaaas/items/4662237cfb7b92f0f839)