---
description: "FastAPI 项目布局详解的约定：轻量多文件、领域分包"
---

# FastAPI 项目布局详解

## 轻量多文件

适用于小型服务、10 个接口左右、1-2 个业务领域：

```
my_app/
├── __init__.py
├── main.py          # FastAPI app 入口 + 路由注册
├── router.py        # 路由（接口多时可拆成 router_xxx.py）
├── models.py        # SQLModel 数据库模型
├── schemas.py       # Pydantic 入参/出参
├── service.py       # 业务逻辑
├── deps.py          # 依赖注入
└── config.py        # 配置
```

作为一个 Python 包组织，包内用相对导入 `from .models import Xxx`，外部通过 `pip install -e .` 安装后用绝对导入。

main.py 示例：
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
from .router import router

@asynccontextmanager
async def lifespan(app: FastAPI):
    yield

app = FastAPI(lifespan=lifespan)
app.include_router(router)
```


## 领域分包

适用于多业务领域、团队协作、长期维护的大项目：

```
src/
├── main.py                   # 入口：创建 app，注册所有 router
├── config.py                 # 全局配置（DATABASE_URL, REDIS_URL 等）
├── database.py               # 数据库连接、Session 工厂
├── models.py                 # 全局基础模型（Base, 时间戳 mixin）
├── exceptions.py             # 全局异常处理器
├── pagination.py             # 通用分页
│
├── auth/                     # ─── 认证领域 ───
│   ├── __init__.py
│   ├── router.py             #   端点定义
│   ├── schemas.py            #   Pydantic 入参/出参
│   ├── models.py             #   数据库模型
│   ├── service.py            #   业务逻辑
│   ├── dependencies.py       #   依赖注入（如 get_current_user）
│   ├── constants.py          #   常量和错误码
│   ├── config.py             #   模块专属环境变量
│   ├── utils.py              #   工具函数（如 hash_password）
│   └── exceptions.py         #   模块专属异常（如 InvalidCredentials）
│
├── posts/                    # ─── 帖子领域（同样的 9 个文件）───
│   └── ...
└── users/                    # ─── 用户领域（同样的 9 个文件）───
    └── ...
```

### 9 个文件各自的职责

| 文件 | 职责 | 示例 |
|------|------|------|
| router.py | 定义 HTTP 端点，只做接/返，不写业务 | `@router.get("/{post_id}")` |
| schemas.py | Pydantic 模型，定义入参出参的形状 | `PostCreate`, `PostResponse` |
| models.py | SQLModel/SQLAlchemy 数据库表定义 | `class Post(Base, table=True)` |
| service.py | 业务逻辑，查库、计算、组合数据 | `create()`, `get_by_id()` |
| dependencies.py | 依赖注入，做请求级校验 | `valid_post_id()`, `valid_owned_post()` |
| constants.py | 常量、枚举、错误码 | `ErrorCode.POST_NOT_FOUND` |
| config.py | 模块专属的 BaseSettings | `PostsConfig(MAX_POSTS_PER_USER=100)` |
| utils.py | 非业务工具函数 | `slugify()`, `truncate()` |
| exceptions.py | 模块专属异常类 | `PostNotFound(HTTPException)` |

### 关键规则

**依赖方向单向，绝不反向：**
```
router → dependencies → service → models
```
schemas / constants / config / utils / exceptions 是底层工具，任何层都可以用，但它们不依赖上面的层。

**跨模块用绝对导入 + 别名：**
```python
from src.auth import constants as auth_constants
from src.auth.dependencies import get_current_user
```

**main.py 只做注册：**
```python
from fastapi import FastAPI
from src.auth.router import router as auth_router
from src.posts.router import router as posts_router

app = FastAPI()
app.include_router(auth_router, prefix="/auth", tags=["Auth"])
app.include_router(posts_router, prefix="/posts", tags=["Posts"])
```
