POST送信されたパラメータをFlaskで受けるときにrequest has no attribute 'form'（ついでにFlaskのスタートアップガイド）

#目的
研修用の教材をFlaskで作っていて、リクエストパラメータを受け取るときにハマったので。

序盤は普通にFlaskチュートリアルっぽい感じです。
ハマったところまで飛ばしたい方は<a href="https://qiita.com/bowtin/items/194c1f3b1211d7892ab8#%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E8%A9%B1">ハマった話</a>か<a href="https://qiita.com/bowtin/items/194c1f3b1211d7892ab8#%E7%B5%90%E8%AB%96">結論</a>へどうぞ。

#やったこと
##まずはHello World

pipやcondaを使ってflaskをインストールしておきます。

~~~bash
pip install flask
~~~

その後、適当なディレクトリにプログラムを作っていきます。

~~~python:app.py
# coding: utf-8
from flask import Flask, render_template

# Webサーバインスタンスの生成
app = Flask(__name__) 

# http://localhost:5000/にリクエストが来たときの処理
@app.route("/")
def index():
    return "Hello Flask!"

if __name__ == "__main__":
    # webサーバーの立ち上げ
    app.run()
~~~

その後、コンソール上でapp.pyが保存されているディレクトリまで移動し、

~~~bash
python app.py
~~~

これでサーバが立ち上がりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495652/4c8fec60-4ed5-e5d0-9eb1-7d38b2a30691.png)


問題なさそうです。

##「ログイン画面→ようこそ、◯◯さん」まで作る
次に、リクエストパラメータを試してみたかったので、フォームへの入力＋画面遷移のところまでやってみようと思いました。

###ログイン画面の作成

リクエストパラメータを受け取ってみようということになって、とりあえずログイン画面を作りました。ログイン画面なので、よく見る感じでPOST送信にしておきます。
また、ユーザ名はusername、パスワードはpasswordという名前で送信されることにしておきます。
また、formのaction属性はとりあえずlogin_managerとしておきます。後ほど使います。

~~~html:login.html
<html>
    <head>

    </head>

    <body>
        <form action="/login_manager" method="POST">
            <input type="text" name="username" placeholder="Your name">
            <input type="password" name="password" placeholder="Your password">
            <input type="submit" value="login">
        </form>
    </body>
</html>
~~~

###app.pyへの登録
先程のapp.pyで分かる通り、app.pyはURLと実行される処理の紐付けを行っているような立ち位置なので、このlogin.htmlに関してもapp.pyへ追加しておきます。

~~~python:app.py
# coding: utf-8
from flask import Flask, render_template

app = Flask(__name__) 

@app.route("/")
def index():
    return "Hello Flask!"

@app.route("/login") #追加
def login():
    return render_template("login.html")

if __name__ == "__main__":
    # webサーバー立ち上げ
    app.run()
~~~

サーバを再度立ち上げて、今度は[http://localhost/login](http://localhost/login)で試してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495652/fde2848d-5970-3778-cbf1-a568cbb94551.png)
問題なさそう。

###app.pyに処理を追加
[http://localhost:5000/login_manager](http://localhost:5000/login_manager)にリクエストが来たときの処理をapp.pyに追加します。login_managerは、以前にlogin.htmlを作成したときのformのaction属性で指定しています。

~~~python:app.py
# coding: utf-8
from flask import Flask, render_template

app = Flask(__name__) 

@app.route("/")
def index():
    return "Hello Flask!"

@app.route("/login") 
def login():
    return render_template("login.html")

@app.route("/login_manager", methods=["POST"])  #追加
def login_manager():
    return "ようこそ、" + request.form["username"] + "さん"

if __name__ == "__main__":
    # webサーバー立ち上げ
    app.run()
~~~

##ハマった話
さて、ここがハマった話です。
上のコードのlogin_manager部分で、requet.form["username"]としているのですが、いざリクエストを送ってみると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495652/26b1cb10-5ffd-2025-1745-1951d2724aa7.png)

な、なにぃ～～

慌ててサーバログを除くと...

~~~bash
return "ようこそ、" + request.form["username"] + "さん"
NameError: name 'request' is not defined
~~~

あ、はいはいわかったわかった。
import requestだな！と思ってimport文をapp.pyに追加。

意気揚々とサーバを再起動するも、またもや500番台エラー。
ただ良くログを見ると今度は若干違っていて...

~~~bash
return "ようこそ、" + request.form["username"] + "さん"
AttributeError: module 'request' has no attribute 'form'
~~~

##結論
~~~python
import request
~~~
ではなく

~~~python
from flask import request
~~~
でした。

同一モジュール名ですが、パッケージが違っていたようです。
常識かもしれないんだけど、初心者からするとなんともややこしい。

#まとめ
FlaskでPOST送信されたパラメータを受け取りたいときはこう。

~~~python
from flask import request
~~~

実際にPOST送信されたパラメータを受け取るときはこう。
 
~~~python
request.form["パラメータ名"]
~~~

ちなみに、GET送信されたパラメータの場合はこうらしい。

~~~python
request.args.get("パラメータ名")
~~~