FastAPIとは?
バックエンドAPIの開発において以下の技術の有難さを痛いほど分かっている人にとっては今更感あります。
この記事はAPIを作った経験がない入門者に向けて、FastAPI1の解説を分かりやすく書いています。
- Python decolator
- Hot Reload
- Swagger
- Dependency機能
Python decolator
PythonのWebフレームワークでどこでも出てくるデコレータ。
以下のような@app.<method>(path)
という見た目をしています。
app = FastAPI()
@app.get("/post/")
def getPost(id):
return {"id": id, "title": "A title has to be bold style."}
@app.get
=(app
インスタンスのget
メソッド)なのでその実装を辿ると、APIルートとしてラップされた関数を追加しているようです。つまり、app
インスタンスはHTTPのメソッドとパスが一致している場合に、デコレータでラップされた関数を呼び出します。
Pythonのデコレータは単なる糖衣構文です。
関数内の処理結果や関数自体をトラッキングするための方法と考えておけば無難です。
最初は戸惑いますけどね・・・。
Hot Reload
ReactやFlutterを触ったことのある人はその時の体験を思い出してみてください。
Hot Reloadはソースコードの変更箇所を検知して、変更前の情報をできるだけ保持したまま再読み込みができる機能です。開発段階で間違ったコードを書いたとしても、修正結果を素早く反映できます。
例えば、投稿型サービスを作る際に、ゲストには投稿権限をつけないとします。
この機能を実装するためには、以下のように現在のユーザに依存(Depends)させます。
from fastapi import Depends
@app.post("/post/")
- def addPost(title, content):
+ def addPost(title, content, current_user: User = Depends(get_current_user)):
id = Post.add(title, content)
return {"id": id}
この変更を行ってファイルを保存した際、現在ログインしていないユーザの投稿操作が即座にブロックされます。
IDEに付いてくるRunボタンは最初のステートに戻ってしまいますが、Hot Reloadはステートを保持できるので開発体験が向上します。
Swagger
SwaggerはAPIのPlayground兼ドキュメントだと思ってください。Gitbookなどのエンタープライズ向け文書化ツールにはAPIエンドポイント専用のテンプレートが存在しますが、自分で書き込む必要があります。
Swaggerでは定義したエンドポイントをすぐに確認できるのでとても便利です。こんな感じに見れるよ。
(とりあえず作ってる途中のやつをあげIとは?
バックエンドAPIの開発において以下の技術の有難さを痛いほど分かっている人にとっては今更感あります。
この記事はAPIを作った経験がない入門者に分かりやすく書いています。
- Python decolator
- Hot Reload
- Swagger
- Dependency機能
Python decolator
PythonのWebフレームワークでどこでも出てくるデコレータ。
以下のような@app.<method>(path)
という見た目をしています。
app = FastAPI()
@app.get("/post/")
def getPost(id):
return {"id": id, "title": "A title has to be bold style."}
@app.get
=(app
インスタンスのget
メソッド)なのでその実装を辿ると、APIルートとしてラップされた関数を追加しているようです。つまり、app
インスタンスはHTTPのメソッドとパスが一致している場合に、デコレータでラップされた関数を呼び出す処理をします。
Pythonのデコレータは単なる糖衣構文です。
関数内の処理結果や関数自体をトラッキングするための方法と考えておけば無難です。
最初は戸惑いますけどね・・・。
Hot Reload
ReactやFlutterを触ったことのある人はその時の体験を思い出してみてください。
Hot Reloadはソースコードの変更箇所を検知して、変更前の情報をできるだけ保持したまま再読み込みができる機能です。開発段階で間違ったコードを書いたとしても、修正結果を素早く反映できます。
例えば、投稿型サービスを作る際に、ゲストには投稿権限をつけないとします。
この機能を実装するためには、以下のように現在のユーザに依存(Depends)させます。
from fastapi import Depends
@app.post("/post/")
- def addPost(title, content):
+ def addPost(title, content, current_user: User = Depends(get_current_user)):
id = Post.add(title, content)
return {"id": id}
この変更を行ってファイルを保存した際、現在ログインしていないユーザの投稿操作が即座にブロックされます。
IDEに付いてくるRunボタンは最初のステートに戻ってしまいますが、Hot Reloadはステートを保持できるので開発体験が向上します。2
Swagger
SwaggerはAPIのPlayground兼ドキュメントだと思ってください。Gitbookなどのエンタープライズ向け文書化ツールにはAPIエンドポイント専用のテンプレートが存在しますが、自分で書き込む必要があります。
Swaggerでは定義したエンドポイントをすぐに確認できるのでとても便利です。こんな感じに見れるよ。
(とりあえず見栄えが良さそうなものを)
Example Valueの参照元
型ヒントで指定します。
まずpydanticやtypingなどのスキーマを定義するモジュールをインポートしましょう。
from pydantic import BaseModel, Field
from typing import List, Dict
次にBaseModelを継承しスキーマを定義します。
class Timeline(BaseModel):
similarityArray: List[int] = Field([],
example=[1, 2],
description='content ranking over the given query')
dateArray: List[int] = Field([],
example=[2, 1],
description='content timeline')
metadata: Dict[int, Metadata] = Field({}, example={1: Metadata()})
以下の関数において、返り値の型であるTimeline
はBaseModel
を継承しているので、Swagger UIのExample Valueにスキーマのサンプル値が表示されます。
@app.put("/v1/timeline/")
def get_timeline(query: TimelineQuery) -> Timeline:
return Timeline()
FastAPIはスキーマや型をきっちり書くことを前提に設計されているような印象を受けます。3
Swagger UIに説明を集約できるメリットはぜひ活用したいですね。
Dependency機能
新しいポストをデータベースからフェッチしたい場合、どうしたらよいでしょうか?
少し、情報を整理します。
- FastAPIのデコレータを使用すると、ポストを取得するエンドポイントを作成できます。
- 引数には、クエリパラメータを指定します。
では、データベースはどうやって関数に渡すのかというと、FastAPIのDepends
クラスを利用します。
以下の関数では、ユーザとデータベースをAPIルートに依存させています。
@app.get(path="/users/", tags=["Users"])
async def users(current_user: str = Depends(get_current_user),
session: Session = Depends(get_db)):
return User.getUserInfo(session, current_user)
こうすることで、
- ログインが必要であること
- データベース操作を含むこと
を明示でき、意図がつかみやすいソースコードになっています。
文字通り、Dependsクラスは依存対象を表現する手段だと考えてください。
第一回のまとめ
✅ Pythonのデコレータは関数内の処理結果や関数自体をトラッキングするための表現方法の一つです。
✅ Hot Reloadはステートを保持できるので開発体験が向上します。
✅ 型やスキーマをきっちり書くことで、Swagger UIにドキュメントを集約できます。
✅ Dependsクラスは依存対象を表現する手段です。