fastapi-expert について
非同期 Python と Pydantic V2 を使った FastAPI 開発向けのスキルです。API の設計、実装、セキュリティ、テストを案内し、よく使う作業の参考資料も備えています。
主な機能
- 01API と Pydantic スキーマの設計
- 02非同期エンドポイントと DB 操作の構築
- 03JWT 認証と認可の実装
- 04pytest と httpx によるテスト
- 05トピック別リファレンスの参照
活用シーン
- 01FastAPI で REST API を作成
- 02Pydantic V2 のリクエスト検証を追加
- 03非同期 DB アクセスと JWT セキュリティを実装
- 04エンドポイントをテストし OpenAPI ドキュメントを確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jeffallan/ claude-skills --skill fastapi-expertインストール後、Claude Code で/fastapi-expertを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/async-sqlalchemy.mdauthentication.mdendpoints-routing.mdmigration-from-django.mdpydantic-v2.mdtesting-async.md詳細
FastAPI エキスパート
非同期 Python、Pydantic V2、FastAPI による本番環境向け API 開発に関する深い専門知識を提供します。
このスキルを使用する場面
- FastAPI で REST API を構築する
- Pydantic V2 のバリデーションスキーマを実装する
- 非同期データベース操作を設定する
- JWT 認証/認可を実装する
- WebSocket エンドポイントを作成する
- API のパフォーマンスを最適化する
基本的なワークフロー
- 要件を分析する — エンドポイント、データモデル、認証の要件を特定します
- スキーマを設計する — バリデーション用の Pydantic V2 モデルを作成します
- 実装する — 適切な依存性注入を使用して非同期エンドポイントを記述します
- セキュリティを確保する — 認証、認可、レート制限を追加します
- テストする — pytest と httpx で非同期テストを記述します。エンドポイントグループごとに
pytestを実行し、/docsで OpenAPI ドキュメントを確認します
各ステップ後のチェックポイント: スキーマが正しく検証されること、エンドポイントが想定どおりの HTTP ステータスコードを返すこと、次に進む前に
/docsに意図した API の内容が反映されていることを確認します。
最小限の完全な例
スキーマ、エンドポイント、依存性注入をひとまとまりにした例です。
# schemas.py
from pydantic import BaseModel, EmailStr, field_validator, model_config
class UserCreate(BaseModel):
model_config = model_config(str_strip_whitespace=True)
email: EmailStr
password: str
name: str | None = None
@field_validator("password")
@classmethod
def password_strength(cls, v: str) -> str:
if len(v) < 8:
raise ValueError("Password must be at least 8 characters")
return v
class UserResponse(BaseModel):
model_config = model_config(from_attributes=True)
id: int
email: EmailStr
name: str | None = None
# routers/users.py
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Annotated
from app.database import get_db
from app.schemas import UserCreate, UserResponse
from app import crud
router = APIRouter(prefix="/users", tags=["users"])
DbDep = Annotated[AsyncSession, Depends(get_db)]
@router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(payload: UserCreate, db: DbDep) -> UserResponse:
existing = await crud.get_user_by_email(db, payload.email)
if existing:
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Email already registered")
return await crud.create_user(db, payload)
# crud.py
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models import User
from app.schemas import UserCreate
from app.security import hash_password
async def get_user_by_email(db: AsyncSession, email: str) -> User | None:
result = await db.execute(select(User).where(User.email == email))
return result.scalar_one_or_none()
async def create_user(db: AsyncSession, payload: UserCreate) -> User:
user = User(email=payload.email, hashed_password=hash_password(payload.password), name=payload.name)
db.add(user)
await db.commit()
await db.refresh(user)
return user
JWT 認証スニペット
# security.py
from datetime import datetime, timedelta, timezone
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from typing import Annotated
SECRET_KEY = "<jwt-secret>" # use os.environ / settings
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token")
def create_access_token(subject: str, expires_delta: timedelta = timedelta(minutes=30)) -> str:
payload = {"sub": subject, "exp": datetime.now(timezone.utc) + expires_delta}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]) -> str:
try:
data = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
subject: str | None = data.get("sub")
if subject is None:
raise ValueError
return subject
except (JWTError, ValueError):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
CurrentUser = Annotated[str, Depends(get_current_user)]
リファレンスガイド
状況に応じて詳細なガイダンスを参照します。
| トピック | リファレンス | 参照する場面 |
|---|---|---|
| Pydantic V2 | references/pydantic-v2.md | スキーマ、バリデーション、model_config の作成 |
| SQLAlchemy | references/async-sqlalchemy.md | 非同期データベース、モデル、CRUD 操作 |
| エンドポイント | references/endpoints-routing.md | APIRouter、依存関係、ルーティング |
| 認証 | references/authentication.md | JWT、OAuth2、get_current_user |
| テスト | references/testing-async.md | pytest-asyncio、httpx、フィクスチャ |
| Django からの移行 | references/migration-from-django.md | Django/DRF から FastAPI への移行 |
制約事項
必ず行うこと
- あらゆる箇所で型ヒントを使用する(FastAPI では必須です)
- Pydantic V2 の構文(
field_validator、model_validator、model_config)を使用する - 依存性注入には
Annotatedパターンを使用する - すべての I/O 操作で async/await を使用する
Optional[X]ではなくX | Noneを使用する- 適切な HTTP ステータスコードを返す
- エンドポイントをドキュメント化する(OpenAPI が自動生成されます)
絶対に行わないこと
- 同期データベース操作を使用する
- Pydantic のバリデーションを省略する
- パスワードを平文で保存する
- レスポンスで機密データを公開する
- Pydantic V1 の構文(
@validator、class Config)を使用する - 同期コードと非同期コードを不適切に混在させる
- 設定値をハードコードする
出力テンプレート
FastAPI の機能を実装する際は、以下を提示してください。
- スキーマファイル(Pydantic モデル)
- エンドポイントファイル(エンドポイントを含むルーター)
- データベースを使用する場合は CRUD 操作
- 重要な設計判断についての簡潔な説明
ナレッジリファレンス
FastAPI、Pydantic V2、非同期 SQLAlchemy、Alembic マイグレーション、JWT/OAuth2、pytest-asyncio、httpx、BackgroundTasks、WebSockets、依存性注入、OpenAPI/Swagger
@jeffallan(Synergetic Solutions のプリンシパルコンサルタント)がメンテナンスしています。
コメント
Markdown 対応