Python初心者がBottleを使ってみたら案外簡単に動いてくれた

#はじめに
自分用メモです、経緯は下記。

* 1週間前くらいからPython始めて、サーバで何か動かしてみたくなった。
* Webフレームワークの種類を調べてみた。
 * Djangoが一番人気というか間違いないっぽい、けど初心者には少しハードル高そう。
 * いきなり挫折したくないので、とりあえず初心者向けっぽいBottleを選択。

#実行環境
* OS X 10.9.5
* python 3.5.1
* PyCharm Community Edition 2016.1.2


#やりたいこと
* とりあえず動かしてみる。
* ダイナミックなルーティングをしてみる
	* 受け取ったパラメータを利用する
	* パラメータに制約を与える
* GET, POSTしてみる
* エラーページを表示してみる

#やったこと
##とりあえず動かしてみる。
難しいことは考えず、まずはブラウザでHello Worldが表示されるところまでやってみる。

```bash
#importするためにpip installしておく
$ pip install bottle
```

```python
# -*- coding:utf-8 -*-

from bottle import route, run


@route('/hello')
def hello():
    return "Hello World!"


run(host='localhost', port=8080, debug=True)
```
PyCharmでRunして、ブラウザで開いてみる。
http://localhost:8080/hello

![image](https://qiita-image-store.s3.amazonaws.com/0/68671/c564e173-16bd-e6e7-92fb-18cc8abc8f7e.png)

これだけでHello Worldがブラウザで見られるようになった!!すごいなBottle

##ダイナミックなルーティングをしてみる
```python
# -*- coding:utf-8 -*-

from bottle import route, run


@route('/hello/')
@route('/hello/<user>')
def hello(user="taro"):
    return "Hello {user}".format(user=user)


@route('/date/<month:re:[a-z]+>/<day:int>/<path:path>')
def date(month, day, path):
    return "{month}/{day} {path}".format(month=month, day=day, path=path)


run(host='localhost', port=8080, debug=True)
```
###受け取ったパラメータを利用する
実行されるメソッドの引数にデフォルトを定義しておくことでuserが渡されない時にも表示できる。
http://localhost:8080/hello/
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/0b17bdd4-497a-be51-07ef-d80f9f39d1e6.png)

http://localhost:8080/hello/masaibar
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/6875170e-e112-fa3e-74c6-ddc1746c00f1.png)



###パラメータに制約を与える
簡単な値の制約を与えることが出来る。

* re 正規表現
* int int値
* path /をパスの一部として認識してくれる

http://localhost:8080/date/april/29//dev/null
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/3a94fa27-2f14-b75f-d14c-b2b03ee4aef4.png)


##GET, POSTしてみる
GETやPOSTなどのアノテーションには2種類の書き方があるらしい。
@get('/hoge') と @route('/hoge', method='GET') は同じ動作をする。

渡された値は下記の変数を参照して受け取る。

* GETリクエストの場合はrequest.query
* POSTリクエストの場合はrequest.forms

他にもヘッダやリクエスト本文などいろいろなデータを受け取ることが出来る。[参考](http://qiita.com/tomotaka_ito/items/62fc4d58d1be7867a158)

```python
# -*- coding:utf-8 -*-

from bottle import route, run
from bottle import get, post, request


@route('/login', method='GET')  # or @get('/login')
def login():
    username = request.query.get('user')
    password = request.query.get('pass')

    #GETで何も渡されていない時はusername,passwordに何も入れない
    username = "" if username is None else username
    password = "" if password is None else password

    return '''
    <form action="/login" method="post">
            Username: <input name="username" type="text" value="{username}"/>
            Password: <input name="password" type="password" value="{password}"/>
            <input value="Login" type="submit" />
        </form>
    '''.format(username=username, password=password)


@route('/login', method='POST')  # or @post('/post')
def do_login():
    username = request.forms.get('username')
    password = request.forms.get('password')

    return "{username} {password}".format(username=username, password=password)


run(host='localhost', port=8080, debug=True)
```
###GET
http://localhost:8080/login
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/23281c22-76b1-0562-13cc-1016bd797047.png)

http://localhost:8080/login?user=hoge&pass=fuga
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/0896de74-5d15-9527-966a-0b7ea155365a.png)

###POST
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/0d908f8b-531e-79fd-2105-bb119329e6e6.png)


##エラーページを表示してみる
```python
# -*- coding:utf-8 -*-

from bottle import route, run
from bottle import error


@route('/hello')
def hello():
    return "Hello World!"


@error(404)
def error404(error):
    return "Nothing here sorry {error}".format(error=error)


run(host='localhost', port=8080, debug=True)
```
わざと有りもしないURLを踏んでみる。
http://localhost:8080/hellow
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/857a2e78-232f-5788-cf6a-4f73c63a8928.png)



#おわりに
思ったよりも簡単に動いてくれて正直驚きました。
今回は特にテンプレートとか考えないで動かすことに重きを置いていましたが、調べてみるとテンプレートエンジンだけ差し替えて使っている人が結構いる感じでした。
([Jinja2](http://jinja.pocoo.org/docs/dev/)が人気なのかな？)

##参考
Tutorial — Bottle 0.13-dev documentation : http://bottlepy.org/docs/dev/tutorial.html
PythonのWebフレームワーク６種をかんたんに紹介 - モジログ : http://mojix.org/2013/04/13/python-six-wafs
BottleのRequest/Responseオブジェクトをマスター - Qiita : http://qiita.com/tomotaka_ito/items/62fc4d58d1be7867a158
PythonではNoneの比較は==ではなくisを使う - こんにちはこんにちはmonmonです！ : http://monmon.hateblo.jp/entry/20110214/1297710749