Python
Pipenv
responder
tortoise-orm

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

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


What is "responder"

pythonを使っている方なら知っている人の多い requestspipenv の作者 kennethreitz が作ったWebフレームワーク。Pythonは DjangoFlask などの登場以降「コレだ!」となるフレームワークが出てこなかったのですが、2018年に突如として登場したのが responder です。

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


  • FlaskとFalconの良いとこどりのようなフレームワーク

  • GraphQL、asyncなど今どき(2019年現在)の機能に対応

  • APIが使いやすい(わかりやすい)

といった感じです。

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


What is "tortoise-orm"

Python製ORMと言えばご存知 SQLAlchemy ですね。しかし、こちらも如何せん古…ご高齢(初回リリース2006年)なので、新しいモノはないかと物色したところ、DjangoのORMをリスペクトして作られた Tortoise ORM を発見。

個人的に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で実行するだけです。

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が立ち上がります。

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 を受け取らないで良いように改良したい。


import responder
from controllers.account import Account

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


Models

もちろん tortoise-orm で実装。

Djangoになれた人であればかなり使いやすいです。

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 にレスポンスの設定(ステータスコード等)をしていくだけなので、視認性がとても良い。

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界の旋風 を是非みなさんもお試しください。