架构目标和目录结构

这一章参考 poster-fastapi 项目的组织方式,讲一个从零搭建企业级 FastAPI 项目的思路。

这里的“企业级”不是指代码写得复杂,而是指项目具备这些基础能力:

  • 配置统一从环境变量读取。
  • 路由、控制器、业务逻辑、数据库模型分层清楚。
  • 数据库使用 SQLAlchemy 2.0,表结构用 Alembic 迁移。
  • 登录后签发 JWT,接口默认需要 Token。
  • 公开接口通过白名单放行。
  • 响应结构统一,异常处理统一。
  • 启动时能检查数据库连接,调试信息不泄露密码。

一、FastAPI 中的 MVC 怎么理解

传统 MVC:

职责
Model数据模型和数据访问
View页面展示
Controller接收请求,组织响应

FastAPI 主要写 API,没有服务端页面,所以可以理解成:

目录对应职责说明
models/ModelSQLAlchemy ORM 模型,对应数据库表
controllers/Controller接收参数,调用 service,返回统一响应
schemas/View ModelPydantic 请求/响应模型,控制 API 输入输出
services/Service业务逻辑,查询数据库、校验规则、组织数据
api/routes/Router只声明 URL、HTTP 方法、文档信息

也就是说,一个请求的大致链路是:

前端请求

api/routes      路由注册

controllers     参数接收、统一响应

services        业务逻辑

models + db     数据库读写

schemas         响应字段过滤

返回 JSON

二、推荐目录结构

my-fastapi/
├── app/
│   ├── __init__.py
│   ├── main.py                         # 创建 FastAPI app,注册中间件、异常、路由
│   │
│   ├── api/
│   │   ├── __init__.py
│   │   ├── router.py                   # 顶层 API 路由聚合
│   │   └── routes/
│   │       ├── __init__.py
│   │       ├── auth_routes.py          # 登录、注册路由
│   │       ├── user_routes.py          # 用户路由
│   │       └── system_routes.py        # 健康检查等系统路由
│   │
│   ├── controllers/
│   │   ├── __init__.py
│   │   ├── auth_controller.py          # 鉴权控制器
│   │   ├── user_controller.py          # 用户控制器
│   │   └── health_controller.py        # 健康检查控制器
│   │
│   ├── services/
│   │   ├── __init__.py
│   │   ├── auth_service.py             # 登录、注册、签发 Token
│   │   └── user_service.py             # 用户业务逻辑
│   │
│   ├── models/
│   │   ├── __init__.py
│   │   └── user.py                     # SQLAlchemy 用户表模型
│   │
│   ├── schemas/
│   │   ├── __init__.py
│   │   ├── auth_schema.py              # 登录注册请求、Token 响应
│   │   ├── user_schema.py              # 用户响应模型
│   │   └── response_schema.py          # 统一响应模型
│   │
│   ├── db/
│   │   ├── __init__.py
│   │   ├── base.py                     # ORM Base
│   │   └── session.py                  # engine、SessionLocal、get_db
│   │
│   ├── dependencies/
│   │   ├── __init__.py
│   │   └── auth.py                     # 获取当前登录用户
│   │
│   ├── middlewares/
│   │   ├── __init__.py
│   │   ├── auth_middleware.py          # JWT 全局鉴权
│   │   └── request_log_middleware.py   # 请求日志
│   │
│   └── core/
│       ├── __init__.py
│       ├── config.py                   # 配置管理
│       ├── security.py                 # JWT、密码哈希
│       ├── response.py                 # success/fail
│       ├── exceptions.py               # 全局异常处理
│       └── logger.py                   # 日志

├── alembic/
│   ├── versions/
│   └── env.py
├── alembic.ini
├── main.py                             # 本地开发启动入口,可选
├── pyproject.toml
├── .env.example
└── README.md

三、每层不要做越界的事

应该做不应该做
routes注册路径、方法、文档信息写业务逻辑
controllers读取参数、调用 service、返回统一响应直接写复杂 SQL
services业务判断、事务组织、数据库查询处理 HTTP 细节
models定义表结构校验前端请求
schemas定义请求/响应结构访问数据库
dependencies复用依赖,如当前用户、数据库会话写具体业务流程
middlewares全局请求拦截,如 JWT、日志查大量业务数据

分层的目标是让代码好找、好测、好改,不是为了把一个简单功能拆成很多文件。

四、企业项目里常见的接口风格

统一挂载 /api

GET  /api/health
POST /api/auth/register
POST /api/auth/login
GET  /api/users

路由文件只负责注册:

router = APIRouter(prefix="/auth", tags=["鉴权"])
router.add_api_route("/login", login_controller, methods=["POST"])

控制器负责响应:

def login_controller(form: LoginRequest, db: Annotated[Session, Depends(get_db)]):
    token_data = login(db, form)
    return success(data=TokenResponse(**token_data).model_dump(mode="json"))

业务层负责真正逻辑:

def login(db: Session, form: LoginRequest) -> dict:
    user = find_user_by_account(db, form.account)
    # 校验密码、签发 Token
    return token_data

这样一个接口出问题时,你能快速判断应该去哪个文件看。