fastapi-structure-guide

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

FastAPI Structure Guide (2026 Optimized Edition)

FastAPI 项目结构指南(2026优化版)

Intent

适用场景

Use this guide whenever generating code for a FastAPI project, specifically when:
  1. Scaffolding a brand new project.
  2. Adding a new feature (e.g., "Add an Order module").
  3. Refactoring existing code to meet 2026 clean architecture standards.
You must strictly adhere to the Core Principles, Project Structure, Development Workflow, and Coding Rules defined below.

每当生成FastAPI项目代码时,请遵循本指南,特别是以下场景:
  1. 搭建全新项目。
  2. 添加新功能(例如:“添加订单模块”)。
  3. 重构现有代码以符合2026版整洁架构标准。
你必须严格遵守以下定义的核心原则项目结构开发工作流编码规则

I. Core Principles

I. 核心原则

Before writing any code, follow these six guiding principles:
  1. Separation of Concerns (Clean Architecture)
    • API Layer: Only reception, validation, HTTP concerns.
    • Service Layer: Pure business logic and orchestration.
    • Repository Layer: All data access (SQL, caching, external services).
    • DB/Model Layer: Data definition (SQLModel).
    • Rule: Never put business logic or raw SQL in API routes or services.
  2. Full Async First
    • All routes, services, repositories must be
      async def
      by default.
    • Use
      async_sessionmaker
      +
      await
      everywhere.
    • Only use sync when absolutely necessary (e.g., legacy libs).
  3. Repository Pattern + Dependency Injection
    • Services never touch Session directly.
    • Use FastAPI
      Depends
      +
      Annotated
      for injection.
    • Flow: DB Session → Repository → Service → API Route.
  4. Mandatory Use of SQLModel
    • All database models and base schemas must use SQLModel (Pydantic v2 + SQLAlchemy 2.0).
    • One class serves as both DB table (
      table=True
      ) and API schema base.
    • Never use raw SQLAlchemy + separate Pydantic models.
    • Always consult
      references/sqlmodel-reference.md
      for exact syntax, schema variants, relationships, and FastAPI integration patterns.
  5. Config Centralization
    • All config via Pydantic Settings v2 (
      BaseSettings
      ).
    • Never hardcode secrets, URLs, or keys.
  6. Mirrored & Layered Testing
    • tests/
      mirrors
      app/
      1:1.
    • Separate
      unit/
      ,
      integration/
      .
    • Use SQLite in-memory + dependency overrides + pytest-asyncio.

在编写任何代码之前,请遵循以下六项指导原则:
  1. 关注点分离(整洁架构)
    • API层:仅负责请求接收、验证及HTTP相关处理。
    • 服务层:纯业务逻辑与流程编排。
    • 仓储层:所有数据访问操作(SQL、缓存、外部服务调用)。
    • 数据库/模型层:数据定义(基于SQLModel)。
    • 规则:绝不在API路由或服务中编写业务逻辑或原生SQL。
  2. 全异步优先
    • 默认情况下,所有路由、服务、仓储都必须使用
      async def
      定义。
    • 全程使用
      async_sessionmaker
      +
      await
    • 仅在绝对必要时使用同步代码(例如:遗留库兼容)。
  3. Repository Pattern + 依赖注入
    • 服务层绝不直接操作Session。
    • 使用FastAPI的
      Depends
      +
      Annotated
      实现依赖注入。
    • 调用流程:数据库Session → 仓储 → 服务 → API路由。
  4. 强制使用SQLModel
    • 所有数据库模型和基础Schema必须使用SQLModel(Pydantic v2 + SQLAlchemy 2.0)。
    • 单个类同时作为数据库表(
      table=True
      )和API Schema基类。
    • 禁止同时使用原生SQLAlchemy和独立的Pydantic模型。
    • 如需精确语法、Schema变体、关系映射及FastAPI集成模式,请务必参考
      references/sqlmodel-reference.md
  5. 配置集中化
    • 所有配置通过Pydantic Settings v2(
      BaseSettings
      )管理。
    • 绝不硬编码密钥、URL或其他敏感配置。
  6. 镜像分层测试
    • tests/
      目录结构与
      app/
      完全1:1镜像。
    • 分离
      unit/
      (单元测试)和
      integration/
      (集成测试)目录。
    • 使用SQLite内存数据库、依赖重写及pytest-asyncio。

II. Recommended Project Structure (2026 Standard)

II. 推荐项目结构(2026标准)

text
my-fastapi-project/
├── app/                          # Core Application
│   ├── __init__.py
│   ├── main.py                   # App factory + lifespan
│   ├── api/                      # 🌐 API Layer
│   │   ├── __init__.py
│   │   └── v1/
│   │       ├── __init__.py
│   │       ├── api.py            # Router aggregation
│   │       └── endpoints/
│   │           ├── __init__.py
│   │           ├── users.py
│   │           └── items.py
│   ├── core/                     # ⚙️ Cross-cutting
│   │   ├── __init__.py
│   │   ├── config.py             # Settings
│   │   ├── logging.py
│   │   ├── security.py
│   │   └── exceptions.py         # Custom HTTP exceptions
│   ├── db/                       # 🗄️ Database
│   │   ├── __init__.py
│   │   ├── session.py            # async_sessionmaker
│   │   ├── models.py             # SQLModel definitions (table=True)
│   │   └── alembic/              # Migrations
│   ├── schemas/                  # 📝 API Schemas (DTOs)
│   │   ├── __init__.py
│   │   └── user.py               # UserCreate, UserResponse, etc.
│   ├── repositories/             # 🗃️ Data Access Layer (NEW)
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── user_repository.py
│   │   └── item_repository.py
│   ├── services/                 # 🧠 Business Logic
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── user_service.py
│   │   └── item_service.py
│   └── dependencies.py           # Centralized Depends functions
├── tests/                        # ✅ Tests (mirrored)
│   ├── __init__.py
│   ├── conftest.py
│   ├── unit/
│   └── integration/
│       └── api/
│           └── v1/
│               └── endpoints/
│                   └── test_users.py
├── .env                          # Gitignored
├── .env.example
├── .gitignore
├── docker-compose.yaml
├── Dockerfile
├── pyproject.toml                # uv + ruff + pyright + pytest-asyncio
└── README.md
text
my-fastapi-project/
├── app/                          # 核心应用代码
│   ├── __init__.py
│   ├── main.py                   # 应用工厂 + 生命周期管理
│   ├── api/                      # 🌐 API层
│   │   ├── __init__.py
│   │   └── v1/
│   │       ├── __init__.py
│   │       ├── api.py            # 路由聚合
│   │       └── endpoints/
│   │           ├── __init__.py
│   │           ├── users.py
│   │           └── items.py
│   ├── core/                     # ⚙️ 横切关注点
│   │   ├── __init__.py
│   │   ├── config.py             # 配置管理
│   │   ├── logging.py
│   │   ├── security.py
│   │   └── exceptions.py         # 自定义HTTP异常
│   ├── db/                       # 🗄️ 数据库相关
│   │   ├── __init__.py
│   │   ├── session.py            # async_sessionmaker配置
│   │   ├── models.py             # SQLModel定义(table=True)
│   │   └── alembic/              # 数据库迁移
│   ├── schemas/                  # 📝 API Schema(DTO)
│   │   ├── __init__.py
│   │   └── user.py               # UserCreate, UserResponse等
│   ├── repositories/             # 🗃️ 数据访问层(新增)
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── user_repository.py
│   │   └── item_repository.py
│   ├── services/                 # 🧠 业务逻辑层
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── user_service.py
│   │   └── item_service.py
│   └── dependencies.py           # 集中式依赖定义
├── tests/                        # ✅ 测试代码(镜像结构)
│   ├── __init__.py
│   ├── conftest.py
│   ├── unit/
│   └── integration/
│       └── api/
│           └── v1/
│               └── endpoints/
│                   └── test_users.py
├── .env                          # 已加入.gitignore
├── .env.example
├── .gitignore
├── docker-compose.yaml
├── Dockerfile
├── pyproject.toml                # uv + ruff + pyright + pytest-asyncio配置
└── README.md

Directory Responsibilities (Updated)

目录职责(更新版)

  • app/schemas/
    : API input/output models (inherits from SQLModel when possible).
  • app/repositories/
    : All DB operations, caching, external API calls. Thin wrapper around SQLModel.
  • app/services/
    : Business rules, orchestration, validation. Depends on repositories.
  • app/db/models.py
    : SQLModel classes with
    table=True
    .
  • app/core/exceptions.py
    : Custom exceptions + HTTPException handlers.

  • app/schemas/
    :API输入/输出模型(尽可能继承自SQLModel)。
  • app/repositories/
    :所有数据库操作、缓存、外部API调用。是SQLModel的轻量封装。
  • app/services/
    :业务规则、流程编排、校验逻辑。依赖于仓储层。
  • app/db/models.py
    :带有
    table=True
    的SQLModel类定义。
  • app/core/exceptions.py
    :自定义异常 + HTTPException处理器。

III. Creation Rules (Development Workflow)

III. 创建规则(开发工作流)

When adding a new feature, follow these 6 Standard Steps in strict order:
Before Step A: Read
references/sqlmodel-reference.md
.
Step A: Database Model
Add SQLModel class in
app/db/models.py
(or split file if large).
Step B: API Schemas
Create
app/schemas/resource.py
(Create/Update/Response variants).
Step C: Repository
Create
app/repositories/resource_repository.py
(CRUD methods).
Step D: Service
Create
app/services/resource_service.py
(business logic using repository).
Step E: API Endpoint
Create
app/api/v1/endpoints/resource.py
(thin routes).
Step F: Registration & Testing
  1. Register router in
    app/api/v1/api.py
    .
  2. Write mirrored tests in
    tests/integration/
    .

添加新功能时,请严格按照以下6个标准步骤执行:
步骤A之前:阅读
references/sqlmodel-reference.md
步骤A:数据库模型
app/db/models.py
中添加SQLModel类(如果文件过大可拆分)。
步骤B:API Schema
创建
app/schemas/resource.py
(包含Create/Update/Response等变体)。
步骤C:仓储实现
创建
app/repositories/resource_repository.py
(实现CRUD方法)。
步骤D:服务实现
创建
app/services/resource_service.py
(基于仓储实现业务逻辑)。
步骤E:API端点
创建
app/api/v1/endpoints/resource.py
(轻量路由定义)。
步骤F:注册与测试
  1. app/api/v1/api.py
    中注册新路由。
  2. tests/integration/
    中编写镜像结构的测试代码。

IV. Coding Rules (2026 Modern Examples)

IV. 编码规则(2026现代示例)

Rule 0: SQLModel Strict Compliance

规则0:严格遵守SQLModel规范

All SQLModel code must exactly match patterns in
references/sqlmodel-reference.md
. Any deviation must be rejected and corrected.
所有SQLModel代码必须
references/sqlmodel-reference.md
中的示例完全一致。任何偏差都必须被修正。

Rule 1: API Routes Must Be Thin & Async

规则1:API路由必须轻量且异步

python
undefined
python
undefined

✅ Correct

✅ 正确示例

@router.post("/users", response_model=UserResponse) async def create_user( user_in: UserCreate, service: UserService = Depends(get_user_service), ): return await service.create_user(user_in)
undefined
@router.post("/users", response_model=UserResponse) async def create_user( user_in: UserCreate, service: UserService = Depends(get_user_service), ): return await service.create_user(user_in)
undefined

Rule 2: Repository Pattern (Data Access)

规则2:Repository Pattern(数据访问)

python
undefined
python
undefined

app/repositories/user_repository.py

app/repositories/user_repository.py

from sqlmodel.ext.async_session import AsyncSession from sqlmodel import select from app.db.models import User
class UserRepository: def init(self, session: AsyncSession): self.session = session
async def create(self, user: User) -> User:
    self.session.add(user)
    await self.session.commit()
    await self.session.refresh(user)
    return user

async def get_by_email(self, email: str) -> User | None:
    statement = select(User).where(User.email == email)
    result = await self.session.exec(statement)
    return result.first()
undefined
from sqlmodel.ext.async_session import AsyncSession from sqlmodel import select from app.db.models import User
class UserRepository: def init(self, session: AsyncSession): self.session = session
async def create(self, user: User) -> User:
    self.session.add(user)
    await self.session.commit()
    await self.session.refresh(user)
    return user

async def get_by_email(self, email: str) -> User | None:
    statement = select(User).where(User.email == email)
    result = await self.session.exec(statement)
    return result.first()
undefined

Rule 3: Service Layer (Business Logic)

规则3:服务层(业务逻辑)

python
undefined
python
undefined

app/services/user_service.py

app/services/user_service.py

class UserService: def init(self, repo: UserRepository): self.repo = repo
async def create_user(self, data: UserCreate) -> User:
    # Business rules here
    if await self.repo.get_by_email(data.email):
        raise UserAlreadyExists()
    user = User(**data.model_dump(exclude={"password"}))
    # hash password etc.
    return await self.repo.create(user)
undefined
class UserService: def init(self, repo: UserRepository): self.repo = repo
async def create_user(self, data: UserCreate) -> User:
    # 业务规则实现
    if await self.repo.get_by_email(data.email):
        raise UserAlreadyExists()
    user = User(**data.model_dump(exclude={"password"}))
    # 密码哈希等操作
    return await self.repo.create(user)
undefined

Rule 4: Dependencies (centralized)

规则4:依赖定义(集中化)

python
undefined
python
undefined

app/dependencies.py

app/dependencies.py

from fastapi import Depends from sqlmodel.ext.async_session import async_sessionmaker
async def get_db() -> AsyncSession: async with sessionmaker() as session: # from db/session.py yield session
def get_user_repository(db: AsyncSession = Depends(get_db)) -> UserRepository: return UserRepository(db)
def get_user_service(repo: UserRepository = Depends(get_user_repository)) -> UserService: return UserService(repo)
undefined
from fastapi import Depends from sqlmodel.ext.async_session import async_sessionmaker
async def get_db() -> AsyncSession: async with sessionmaker() as session: # 来自db/session.py yield session
def get_user_repository(db: AsyncSession = Depends(get_db)) -> UserRepository: return UserRepository(db)
def get_user_service(repo: UserRepository = Depends(get_user_repository)) -> UserService: return UserService(repo)
undefined

Rule 5: SQLModel Usage

规则5:SQLModel使用示例

python
undefined
python
undefined

app/db/models.py

app/db/models.py

from sqlmodel import SQLModel, Field
class User(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) email: str = Field(index=True, unique=True) hashed_password: str
undefined
from sqlmodel import SQLModel, Field
class User(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) email: str = Field(index=True, unique=True) hashed_password: str
undefined