さきほどの続き
[質問]
FastAPIでの具体的なコード例を見せてください
[回答] Gemini
FastAPIでは、デコレータ(@app.post など)を使用して、HTTPメソッドとPythonの関数を直感的に紐付けることができます。
前述の使い分けに基づいた、シンプルなブログ記事管理のコード例を紹介します。
FastAPIによる実装例
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
# 擬似的なデータベース(辞書型)
db = {
1: {"title": "Hello World", "content": "Initial post content."}
}
# データモデルの定義
class PostCreate(BaseModel):
title: str
content: str
class PostUpdate(BaseModel):
title: Optional[str] = None
content: Optional[str] = None
# 1. POST: 新規作成
@app.post("/posts")
def create_post(post: PostCreate):
new_id = max(db.keys()) + 1
db[new_id] = post.model_dump()
return {"id": new_id, "data": db[new_id]}
# 2. PUT: 全置換(リソースを丸ごと入れ替える)
@app.put("/posts/{post_id}")
def replace_post(post_id: int, post: PostCreate):
if post_id not in db:
raise HTTPException(status_code=404, detail="Post not found")
# 送信されたデータで完全に上書き
db[post_id] = post.model_dump()
return {"message": "Updated completely", "data": db[post_id]}
# 3. PATCH: 部分更新(変更がある項目だけ上書き)
@app.patch("/posts/{post_id}")
def update_post(post_id: int, post_update: PostUpdate):
if post_id not in db:
raise HTTPException(status_code=404, detail="Post not found")
current_data = db[post_id]
# 送信された(Noneでない)フィールドのみを抽出して更新
update_data = post_update.model_dump(exclude_unset=True)
current_data.update(update_data)
db[post_id] = current_data
return {"message": "Updated partially", "data": db[post_id]}
実装のポイント
1. exclude_unset=True の活用(PATCH)
PATCHメソッドの実装では、Pydanticの model_dump(exclude_unset=True) が非常に便利です。これは「リクエストに含まれていなかったフィールド」を除外してくれるため、「タイトルだけ送られてきたらタイトルだけ更新する」というロジックが簡単に書けます。
2. スキーマの使い分け
- POST/PUT用: 全てのフィールドを必須にする(
PostCreate)。 - PATCH用: 全てのフィールドを
Optionalにし、一部欠けていても受け取れるようにする(PostUpdate)。
3. バリデーション
FastAPIは型ヒントを読み取って自動的にバリデーション(型チェック)を行ってくれるため、不正な形式のデータが送られた場合は、関数が実行される前に 422 Unprocessable Entity を返してくれます。
FastAPIはサーバーを起動して /docs にアクセスすると、これらのメソッドをブラウザから直接テストできる Swagger UI が自動生成されます。
このコードをベースにして、SQLiteなどのデータベースと連携(SQLAlchemyやTortoise ORMなどを使用)させる方向で進めてみましょうか?