Python Web Framework 界に旋風を巻き起こす responder と tortoise-orm

Python界に今新しい風が巻き起こる…？

# What is "responder"
pythonを使っている方なら知っている人の多い [requests](http://python-requests.org) や [pipenv](https://docs.pipenv.org) の作者 [kennethreitz](https://github.com/kennethreitz) が作ったWebフレームワーク。Pythonは [Django](https://www.djangoproject.com) や [Flask](https://www.palletsprojects.com/p/flask/) などの登場以降「コレだ！」となるフレームワークが出てこなかったのですが、2018年に突如として登場したのが [responder](https://python-responder.org) です。

詳しいことは公式ドキュメントを参照してほしいのですが、ざっくり言うと

- FlaskとFalconの良いとこどりのようなフレームワーク
- GraphQL、asyncなど今どき（2019年現在）の機能に対応
- APIが使いやすい（わかりやすい）

といった感じです。
作者も実績は文句なしなので、これは *Python Web Framework界* の覇権最有力候補ではないかと思います。

# What is "tortoise-orm"
Python製ORMと言えばご存知 [SQLAlchemy](https://www.sqlalchemy.org) ですね。しかし、こちらも如何せん古…ご高齢（初回リリース2006年）なので、新しいモノはないかと物色したところ、DjangoのORMをリスペクトして作られた [Tortoise ORM](https://tortoise-orm.readthedocs.io) を発見。
個人的にDjangoの設計思想は好きでして、ModelとSchemeを1つのコードで簡潔でき、さらに `asyncio` に対応していたので、一発で採用決定。
上記理由によりresponderとの相性はかなり良い感じかと思います。

# Sample
https://github.com/shuto-S/sample-responder-tortoise

## 使用技術
- Python 3.7
- pipenv
- responder
- tortoise-orm

## Install and Run
pipenvをインストールしておけば、サンプルのREADMEに書いている通りにコマンドを叩けば動くはずです。tortoise-ormがpipenvに対応していないみたいなので、GitHubから直接取ってくる形になっていますが、一応動いたのでよし。そのうち対応して欲しいですね。
pipenvは `scripts` にコマンドを追加できるので、プロダクトで扱う時も便利ですね。

```
[scripts]
migrate="python migrate.py"
start="python main.py"
```

## Migration
下記のファイルを用意してPythonで実行するだけです。

```py
from tortoise import Tortoise, run_async

async def migrate():
   # connect DB
    await Tortoise.init(
        db_url="sqlite://db.sqlite3",  # DB URL
        modules={"models": ["models"]}  # Modelを書いたファイルを指定
    )

    # run migrate
    await Tortoise.generate_schemas()

run_async(migrate())
```

## Main
書き方は色々とあると思いますが、DBコネクションの接続・切断とルーティングの設定を行い、アプリケーションを立ち上げる `main.py` を作成。
Pythonで実行するとresponderが立ち上がります。

```py
import responder
from tortoise import Tortoise
from router import add_routers

api = responder.API()

# 立ち上げのタイミングでDBへのコネクションを確立
@api.on_event("startup")
async def start_db_connection():
    await Tortoise.init(
        db_url="sqlite://db.sqlite3",
        modules={"models": ["models"]}
    )

# 落とすタイミングでDBコネクションを切断
@api.on_event("shutdown")
async def close_db_connection():
    await Tortoise.close_connections()

# router.pyにてルーティングを設定
add_routers(api)

if __name__ == '__main__':
    api.run(debug=True)
```

## Routing
mainに書いても良かったのですが、Djangoの `urls.py` のようにルーティングだけのファイルが欲しかったので作成。
`api: responder.API` を受け取らないで良いように改良したい。

```py

import responder
from controllers.account import Account

def add_routers(api: responder.API):
    api.add_route("/accounts", Account)
```

## Models
もちろん `tortoise-orm` で実装。
Djangoになれた人であればかなり使いやすいです。

```py
from tortoise.models import Model
from tortoise import fields

class User(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()

    def __str__(self):
        return self.name
```

## Controllers
Djangoにおける `views.py` に相当する。
`router.py` でルーティングの設定、`main.py` でDBコネクションを確立できているので、かなりスッキリ書けました。また、`resp` にレスポンスの設定（ステータスコード等）をしていくだけなので、視認性がとても良い。

```py
from models import User

class Account:
    async def on_get(self, req, resp):
        # とりあえずテスト用のアカウント（ユーザー）を作る
        await User.create(name="Test User")
        
        user = await User.first()
        resp.text = f"Hello, {user.name}"
```

# まとめと所感
`responder` のツボを付いた、かゆいところに手が届く、使いやすいAPI群。
`tortoise-orm` のDjangoチックで明快なORM機能。

一言で言うと **So Good!**

まだ出たばかり（両方2018年に初リリース）なので、使ううちに粗が見えると思うのですが、相性がバッチリなのでこの組み合わせは十分覇権を狙えるポテンシャルを持っています。

サンプルということで、両方とも書いていない機能がたくさんあるので、*Python Web Framework界の旋風* を是非みなさんもお試しください。