FastAPI 项目开发规范:项目结构、分层职责与代码约束
FastAPI 项目开发规范文档本文档用于指导基于 FastAPI 的 Python Web 项目开发约定项目结构、代码分层、编写规范和约束规则。适用于 Agent 类应用及通用后端服务。一、核心设计原则原则说明按业务模块分包按业务能力如user、agent、order组织代码而不是单纯按技术分层组织代码。每个模块包含自己的路由、模型、业务逻辑和数据访问。依赖方向单向依赖关系为业务模块 -core/公共基础设施。平级业务模块之间禁止直接相互调用避免循环依赖。如需跨模块调用通过core/层中转或使用事件机制解耦。Router 薄Service 厚Router 只做 HTTP 协议适配包括解析请求参数、调用 Service、返回响应。所有业务逻辑必须放在 Service 层。函数优先类为辅Service 层和 Repository 层优先使用独立函数不使用无状态类封装除非确实需要维护状态或需要利用继承、多态等能力。二、项目目录结构规范{project_name}/ ├── app/ │ ├── api/ # API 版本管理 │ │ └── v{version}/ # 版本号如 v1 │ │ └── endpoints/ # 路由端点按模块拆分 │ │ ├── {module1}.py # 如 user.py │ │ └── {module2}.py # 如 agent.py │ │ │ ├── core/ # 核心基础设施被所有业务模块依赖 │ │ ├── config.py # 配置管理使用 pydantic-settings │ │ ├── database.py # 数据库连接如异步引擎、会话工厂 │ │ ├── dependencies.py # 公共依赖注入如认证、分页 │ │ ├── exceptions.py # 自定义异常类 │ │ ├── response.py # 统一响应格式 │ │ └── {infra}.py # 其他基础设施如 LLM 客户端、Redis │ │ │ ├── modules/ # 业务模块核心代码 │ │ ├── {module1}/ # 如 user/ │ │ │ ├── schemas.py # Pydantic 模型请求/响应 │ │ │ ├── models.py # ORM 模型如 SQLAlchemy/Tortoise │ │ │ ├── service.py # 业务逻辑函数 │ │ │ └── repository.py # 数据访问函数 │ │ └── {module2}/ # 如 agent/ │ │ ├── schemas.py │ │ ├── models.py │ │ ├── service.py │ │ └── repository.py │ │ │ ├── main.py # FastAPI 应用入口 │ └── __init__.py │ ├── tests/ # 单元测试 │ └── {module}/ # 按模块组织 │ ├── test_service.py │ └── test_repository.py │ ├── .env # 环境变量不提交 Git ├── .env.example # 环境变量示例 ├── requirements.txt # 生产依赖 ├── requirements-dev.txt # 开发依赖 └── pyproject.toml # 项目配置三、各层级职责与约束3.1 Core 层位置app/core/职责提供全局配置、数据库连接、公共依赖、统一响应、异常基类等基础设施。不包含任何业务逻辑。可以被所有业务模块导入依赖。约束Core 层不得导入任何modules/下的模块保持底层独立。配置类必须从环境变量读取敏感信息不得硬编码。3.2 Modules 层3.2.1 Schemasschemas.py职责定义请求数据模型Request Schema。定义响应数据模型Response Schema。使用 PydanticBaseModel进行数据校验和序列化。约束不在 Schema 中编写任何业务逻辑或数据验证以外的代码。响应模型与 ORM 模型分离避免直接暴露数据库字段。使用from_attributes TruePydantic v2支持 ORM 对象转换。3.2.2 Modelsmodels.py职责定义数据库表结构ORM 模型。使用 SQLAlchemy 或其他 ORM 定义表字段、索引、关系。约束不在 Model 中添加业务逻辑方法。字段命名使用下划线风格snake_case。敏感字段如密码不应直接映射到响应 Schema。3.2.3 Repositoryrepository.py职责封装所有数据库 CRUD 操作。提供纯函数接口接收db会话作为参数。约束函数命名规范get_by_*、create_*、update_*、delete_*。不包含业务逻辑如密码加密、数据校验。所有函数为async异步函数。提交事务由调用方Service控制Repository 层不自行提交事务。3.2.4 Serviceservice.py职责包含所有核心业务逻辑。调用 Repository 进行数据操作。处理事务边界包括提交和回滚。调用外部服务如 LLM API、消息队列。约束使用独立函数不使用无状态类封装除非确实需要维护状态。每个业务场景对应一个独立函数。函数命名应清晰表达业务意图如register_user、chat_with_agent。使用async with AsyncSessionLocal() as db:管理数据库会话。正确处理异常并抛出明确的业务异常AppException子类。不直接返回 HTTP 响应只返回业务数据或抛出异常。3.3 API 层Router位置app/api/v{version}/endpoints/职责定义路由和 HTTP 方法如 GET、POST、PUT、DELETE 等。通过 Pydantic Schema 校验请求参数。调用 Service 层执行业务。格式化并返回统一响应。约束Router 中不包含任何业务逻辑只做协议适配。使用APIRouter并指定prefix和tags。使用Depends注入依赖如认证、数据库会话。异常统一转换为 HTTP 异常抛出由全局异常处理捕获。响应格式必须遵循统一的{code, message, data}结构。3.4 应用入口main.py职责创建 FastAPI 应用实例。注册路由。配置中间件如 CORS、日志等。注册全局异常处理。管理应用生命周期包括启动和关闭事件。约束使用lifespan上下文管理器管理资源。路由注册必须通过include_router进行。敏感配置从core/config.py读取。四、关键规范与约束4.1 导入规范正确from app.modules.user import service as user_service正确from app.core.database import get_db禁止业务模块之间直接相互导入如agent导入user禁止循环依赖如 A 导入 BB 又导入 A4.2 异步规范所有数据库操作、外部 API 调用必须使用async/await。同步阻塞代码如 CPU 密集型任务应通过run_in_threadpool放到线程池执行避免阻塞事件循环。4.3 异常处理规范业务异常继承AppException包含错误码和错误信息。Router 层捕获业务异常并转换为 HTTP 异常。全局异常处理器统一格式化错误响应。4.4 事务管理规范事务边界在 Service 层控制。使用async with AsyncSessionLocal() as db:管理会话生命周期。提交事务使用await db.commit()回滚使用await db.rollback()。禁止在 Repository 层自行提交事务。4.5 响应格式规范统一响应格式如下{code:0,message:success,data:{}}字段说明code状态码0表示成功非0表示失败。message提示信息。data业务数据。规范函数success(data, message)返回成功响应。error(message, code)返回错误响应。4.6 依赖注入规范公共依赖如认证定义在core/dependencies.py。使用 FastAPI 的Depends进行依赖注入。每个请求独立的依赖如数据库会话通过Depends(get_db)注入。4.7 测试规范单元测试按模块组织如tests/user/test_service.py。Service 层测试不依赖 HTTP 网络直接调用 Service 函数。使用pytest-asyncio支持异步测试。数据库测试使用独立的测试数据库或内存数据库。五、示例代码片段说明性5.1 Service 层函数签名示例# 正确使用独立函数asyncdefregister_user(data:UserCreateSchema)-UserModel:用户注册业务逻辑asyncwithAsyncSessionLocal()asdb:# 业务逻辑代码...# 错误不推荐使用无状态类classUserService:staticmethodasyncdefregister_user(data:UserCreateSchema)-UserModel:...5.2 Router 层调用示例# 正确Router 薄只做适配router.post(/register)asyncdefregister(data:UserCreateSchema):try:userawaituser_service.register_user(data)returnsuccess(dataUserResponseSchema.model_validate(user))exceptUserAlreadyExistsErrorase:raiseHTTPException(status_code400,detailstr(e))5.3 依赖注入示例# Core 层定义公共依赖asyncdefget_current_user(credentials:HTTPAuthorizationCredentialsDepends(security)):...# Router 层使用依赖router.get(/profile)asyncdefget_profile(current_userDepends(get_current_user)):...5.4 事务管理示例# 正确Service 层控制事务asyncdefupdate_user(user_id:int,data:dict):asyncwithAsyncSessionLocal()asdb:userawaituser_repo.get_by_id(db,user_id)ifnotuser:raiseUserNotFoundError()userawaituser_repo.update(db,user_id,data)awaitdb.commit()returnuser# 错误Repository 层自行提交事务asyncdefupdate(db,user_id,data):...# 不该在这里 commitawaitdb.commit()六、环境变量配置规范所有敏感配置如数据库 URL、API Key、Secret必须从环境变量读取。使用pydantic-settings管理配置。提供.env.example文件列出所有需要的环境变量并去掉真实值。七、代码检查清单提交代码前确认以下事项新功能是否按业务模块分包Service 层是否使用了独立函数而不是无状态类Router 中是否包含业务逻辑业务逻辑应放在 Service 中。是否避免了模块间的循环导入是否编写了对应的单元测试是否正确管理了数据库事务包括 Service 层的 commit/rollbackAPI 响应是否使用了统一格式{code, message, data}敏感信息是否从环境变量读取而不是硬编码是否添加了必要的异常处理和全局异常处理器异步函数是否使用了正确的async/await语法本规范是项目约定所有代码应遵守。如有特殊场景需要偏离规范需在代码审查时说明理由并获得批准。