Chapter 08

ルーター(Routers)

smithonisan
smithonisan
2021.08.23に更新

ルーター(routers)には、前章で登場したパスオペレーション関数を定義していきます。

パスオペレーション関数は、「パス」と「オペレーション」の組み合わせで定義されると説明しました。これが、上記のREST APIにおける「エンドポイント」と「HTTPメソッド」にそれぞれ対応します。

ということは、勘の良い方はおわかりかと思いますが、本書で扱うTODOアプリでは、以下に対応する6つのパスオペレーション関数を定義していくことになります。

  • GET /tasks
  • POST /tasks
  • PUT /tasks/{task_id}
  • DELETE /tasks/{task_id}
  • PUT /tasks/{task_id}/done
  • DELETE /tasks/{task_id}/done

パスオペレーション関数の作成

6つの関数を1つのファイルに持つと、(バランスとしてはとても微妙なところではありますが、)実装を進め、機能を拡張していくにつれてファイルの大きさが肥大化し、見通しが悪くなってしまいます。
そこでファイルの切り方として、リソースごとにファイルを分けるのをおすすめします。

今回のTODOアプリの場合、 /tasks/tasks/{task_id}/done の2つのリソースに大別できるので、それぞれを、 api/routers/task.pyapi/routers/done.py に書いていくことにしましょう。

api/routers/task.py
from fastapi import APIRouter

router = APIRouter()


@router.get("/tasks")
async def list_tasks():
    pass


@router.post("/tasks")
async def create_task():
    pass


@router.put("/tasks/{task_id}")
async def update_task():
    pass


@router.delete("/tasks/{task_id}")
async def delete_task():
    pass
routers/done.py
from fastapi import APIRouter

router = APIRouter()


@router.put("/tasks/{task_id}/done")
async def mark_task_as_done():
    pass


@router.delete("/tasks/{task_id}/done")
async def unmark_task_as_done():
    pass

passについて

ここで、 pass は「何もしない文」を表します。

pythonはインデントに対して厳密であるため、関数は通常 return を返却しますが、特に何も返さない関数の場合 return を書く必要はありません。この後中身を実装するよ、ということをわかりやすくするためにも、ここでは pass と書いておき、先に進みましょう。

これでroutersのプレースホルダの準備は完了です。

しかし、これだけでは先程のSwagger UIには現れてくれません。
上記の2ファイルで作成した router インスタンスを、FastAPIインスタンスに取り込む必要があります。Hello Worldを記述した api/main.py を以下のように書き換えましょう。

api/main.py
from fastapi import FastAPI

from api.routers import task, done

app = FastAPI()
app.include_router(task.router)
app.include_router(done.router)

動作確認

これにより、Swagger UIに、以下のように6つのパスオペレーション関数に対応するエンドポイントが追加されました 🎉

DockerにてFastAPIの環境を構築した際にホットリロードのオプションを追加していますので、FastAPIを再起動しなくても、これまでのファイルを保存するだけで、Swagger UIを開いた際に上記のように最新の状態に反映されているはずです。

async def list_tasks() は、 GET /tasks のパスオペレーションに対応しますが、Swagger UIでは List Tasks という説明を加えられています。
これは、関数名を元に自動生成された説明んです。Swagger UIをリッチでわかりやすいドキュメントとするために、なるべくわかりやすく名が体を表すような関数名をつけるよう心がけましょう。

ここまでの実装は、ただのプレースホルダに過ぎません。その証拠に、以下のように POST /tasks のパスオペレーションを開いてみましょう。

「Execute」を押下しても、Response Bodyには null とだけ返ってきているのがわかります。

次章では、代表的な値を埋めてレスポンスを返すように、「スキーマ」を使って定義していきます。