コンテンツにスキップ

さきほどの続き

[質問]

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などを使用)させる方向で進めてみましょうか?