mcpField
F
fastapi-expert

fastapi-expert

github.com/jeffallan开发12.1k6.2k 次安装今天更新
代码仓库

关于 fastapi-expert

面向 FastAPI 开发的技能,涵盖异步 Python 与 Pydantic V2。它为 API 设计、实现、安全和测试提供指导,并附有常见主题的参考资料。

主要功能

  1. 01设计 API 和 Pydantic 模型
  2. 02构建异步端点与数据库操作
  3. 03实现 JWT 身份验证与授权
  4. 04使用 pytest 和 httpx 测试
  5. 05查阅主题参考指南

适用场景

  1. 01使用 FastAPI 创建 REST API
  2. 02添加 Pydantic V2 请求验证
  3. 03实现异步数据库访问和 JWT 安全机制
  4. 04测试端点并检查 OpenAPI 文档

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jeffallan/claude-skills --skill fastapi-expert

安装后在 Claude Code 中输入/fastapi-expert确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
async-sqlalchemy.md
authentication.md
endpoints-routing.md
migration-from-django.md
pydantic-v2.md
testing-async.md

详细介绍

FastAPI 专家

精通异步 Python、Pydantic V2,以及使用 FastAPI 开发生产级 API。

何时使用此技能

  • 使用 FastAPI 构建 REST API
  • 实现 Pydantic V2 验证模式
  • 配置异步数据库操作
  • 实现 JWT 身份验证/授权
  • 创建 WebSocket 端点
  • 优化 API 性能

核心工作流

  1. 分析需求 — 确定端点、数据模型和身份验证需求
  2. 设计模式 — 创建 Pydantic V2 模型以进行验证
  3. 实现 — 编写异步端点,并正确注入依赖项
  4. 保障安全 — 添加身份验证、授权和速率限制
  5. 测试 — 使用 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 V2references/pydantic-v2.md创建模式、验证和 model_config 时
SQLAlchemyreferences/async-sqlalchemy.md处理异步数据库、模型和 CRUD 操作时
端点references/endpoints-routing.md使用 APIRouter、依赖项和路由时
身份验证references/authentication.md使用 JWT、OAuth2 和 get_current_user 时
测试references/testing-async.md使用 pytest-asyncio、httpx 和 fixtures 时
Django 迁移references/migration-from-django.md从 Django/DRF 迁移到 FastAPI 时

约束

必须做到
  • 在所有地方使用类型提示(FastAPI 要求使用类型提示)
  • 使用 Pydantic V2 语法(field_validator、model_validator、model_config)
  • 使用 Annotated 模式注入依赖项
  • 所有 I/O 操作均使用 async/await
  • 使用 X | None,而不是 Optional[X]
  • 返回恰当的 HTTP 状态码
  • 编写端点文档(自动生成 OpenAPI)
禁止事项
  • 使用同步数据库操作
  • 跳过 Pydantic 验证
  • 以纯文本形式存储密码
  • 在响应中暴露敏感数据
  • 使用 Pydantic V1 语法(@validator、class Config)
  • 不当混用同步和异步代码
  • 将配置值硬编码

输出模板

实现 FastAPI 功能时,提供:

  1. 模式文件(Pydantic 模型)
  2. 端点文件(包含端点的路由器)
  3. 涉及数据库时提供 CRUD 操作
  4. 简要说明关键决策

知识参考

FastAPI、Pydantic V2、异步 SQLAlchemy、Alembic 迁移、JWT/OAuth2、pytest-asyncio、httpx、BackgroundTasks、WebSockets、依赖项注入、OpenAPI/Swagger

由 @jeffallan 维护,他是 Synergetic Solutions 的首席顾问。

文档

评论

支持 Markdown