- 追加された行はこの色です。
- 削除された行はこの色です。
- FastAPI へ行く。
#author("2025-05-19T08:54:57+09:00","","")
#author("2025-05-30T04:51:38+09:00","","")
#mynavi()
#setlinebreak(on);
#mydateinfo(2024-10-06, 2025-05-19)
* 目次 [#k1925e13]
#contents
- 参考
-- ドキュメント: https://fastapi.tiangolo.com/ja/
-- ソースコード: https://github.com/fastapi/fastapi
* 概要 [#t207b1a8]
Python の Webフレームワーク。
以下、公式より引用 ( https://fastapi.tiangolo.com/ja/ )
#html(<div style="border: 1px solid #333; padding: 2px 10px 8px 10px; background: #eee;">)
高速: NodeJS や Go 並みのとても高いパフォーマンス (Starlette と Pydantic のおかげです)。 最も高速な Python フレームワークの一つです。
高速なコーディング: 開発速度を約 200%~300%向上させます。
- 少ないバグ: 開発者起因のヒューマンエラーを約 40%削減します。
- 直感的: 素晴らしいエディタのサポートや オートコンプリート。 デバッグ時間を削減します。
- 簡単: 簡単に利用、習得できるようにデザインされています。ドキュメントを読む時間を削減します。
- 短い: コードの重複を最小限にしています。各パラメータからの複数の機能。少ないバグ。
- 堅牢性: 自動対話ドキュメントを使用して、本番環境で使用できるコードを取得します。
- Standards-based: API のオープンスタンダードに基づいており、完全に互換性があります
#html(</div>)
「NodeJS や Go 並みのとても高いパフォーマンス」というのは本当か。
個人的には、ルーティングに関しては、そこそこのパフォーマンスは出せるかもしれないが、
ビジネスロジックをゴリゴリ書く場合、限界があるのではないかと推測。(検証が必要)
* インストール [#ia24a076]
#myterm2(){{
pip install fastapi
}}
本番環境ではASGI サーバーが必要(以下では Uvicorn を使用)
#myterm2(){{
pip install "uvicorn[standard]"
}}
* サンプル [#j09557f7]
#mycode2(){{
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
}}
* 起動 [#ne05ba9e]
#myterm2(){{
uvicorn main:app --reload
}}
尚、以下のURLでAPIドキュメントを表示可能。
http://127.0.0.1:8000/docs ( Swagger UI )
http://127.0.0.1:8000/redoc ( ReDoc )
* ルーティング等 [#ld695e0a]
- デコレータを使用してルーティングが可能
- クエリ文字列はメソッド引数から取得可能
- POST/PUT 等の入力データは BaseModel を継承したclassにマッピングして取得可能
- POST/PUT 等の入力データは pydantic.BaseModel を継承したclassにマッピングして取得可能
- fastapi.responses モジュールの各クラス(JSONResponse等)を使用して任意のレスポンス/ステータスを返却する事が可能
例)
#mycode2(){{
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
app = FastAPI()
# 動作確認用
class DataHolder:
items = [
{"item_id": "item01", "item_name": "アイテム01", "description": "説明01"},
{"item_id": "item02", "item_name": "アイテム02", "description": "説明02"},
{"item_id": "item03", "item_name": "アイテム03", "description": "説明03"},
]
class Item(BaseModel):
item_id: str
item_name: str
description: str | None = None
@app.get("/")
def root():
return {"message": "this is root"}
@app.get("/items")
def read_items(item_name: str = None): # メソッド引数でクエリ文字列の取得が可能
if item_name:
return [i for i in items if i["item_name"] == item_name]
return DataHolder.items
@app.get("/items/{item_id}") # PATHパラメータは {項目名} で取得可能
def read_item(item_id):
matched = [i for i in DataHolder.items if i["item_id"] == item_id]
if matched:
return matched[0]
return JSONResponse(status_code=404, content={"message": "該当データなし"})
@app.post("/items", status_code=201) # デフォルトのステータス宣言
def new_item(new_item: Item): # BaseModelを継承したclassで入力データの取得が可能
if len([i for i in DataHolder.items if i["item_id"] == new_item.item_id]) > 0:
return JSONResponse(status_code=400, content={"message": "既に登録されています"}) # 任意のステータスを返却する場合
DataHolder.items.append(new_item.dict())
return new_item
@app.put("/items/{item_id}")
def update_item(item_id: str, item: Item):
if len([i for i in DataHolder.items if i["item_id"] == item_id]) == 0:
return JSONResponse(status_code=404, content={"message": "該当データなし"})
upd_item = { "item_id": item_id, "item_name": item.item_name, "description": item.description }
DataHolder.items = [upd_item if i["item_id"] == item_id else i for i in DataHolder.items]
return {"message": "updated"}
@app.delete("/items/{item_id}")
def delete_item(item_id: str):
if len([i for i in DataHolder.items if i["item_id"] == item_id]) == 0:
return JSONResponse(status_code=404, content={"message": "該当データなし"})
DataHolder.items = [i for i in DataHolder.items if i["item_id"] != item_id]
return {"message": "deleted"}
}}
#TODO