【WitSystem】FastAPI目录架构最佳实践
一个“最佳”的FastAPI目录架构,核心肯定是高内聚、低耦合、可扩展性强、便于维护,并能适配从小型项目到大型企业级应用的演进。以下架构参考了FastAPI官方推荐实践、DDD(领域驱动设计)思想及工业界通用标准,同时兼顾了灵活性和规范性。
一、通用目录架构(推荐版)
适用于90%以上的场景(从小型API到中大型服务),结构清晰且无过度设计,可根据项目规模灵活增减模块。
your_project/ # 项目根目录
├── .env # 环境变量(开发环境用,不提交Git)
├── .env.prod # 生产环境变量模板(提交Git,填占位符)
├── .gitignore # Git忽略文件(venv、.env、__pycache__等)
├── README.md # 项目说明(安装、启动、接口文档等)
├── requirements.txt # 依赖包列表(或用pyproject.toml+poetry)
├── pyproject.toml # 项目元信息(推荐用Poetry/Pipenv管理依赖)
├── main.py # 项目入口(启动服务、注册核心组件)
├── core/ # 核心配置(全局通用、不依赖其他模块)
│ ├── __init__.py
│ ├── config.py # 配置中心(读取环境变量、统一配置)
│ ├── exceptions.py # 全局异常定义(自定义错误类)
│ ├── middlewares.py # 全局中间件(日志、跨域、认证等)
│ ├── dependencies.py # 全局依赖(如登录验证、数据库连接)
│ └── logger.py # 日志配置(自定义日志格式、输出)
├── api/ # 接口层(仅负责路由注册和请求/响应处理)
│ ├── __init__.py
│ ├── api_v1/ # API v1版本(支持多版本共存)
│ │ ├── __init__.py
│ │ ├── endpoints/ # 按业务模块拆分路由
│ │ │ ├── __init__.py
│ │ │ ├── user.py # 用户相关接口(/api/v1/users/*)
│ │ │ └── item.py # 商品相关接口(/api/v1/items/*)
│ │ └── router.py # v1版本路由汇总(注册所有endpoints)
│ └── deps/ # 接口层专属依赖(如某模块的权限校验)
│ ├── __init__.py
│ └── user_deps.py # 用户接口的依赖(如“必须是管理员”)
├── app/ # 业务逻辑层(核心业务,与接口解耦)
│ ├── __init__.py
│ ├── crud/ # 数据操作(Create/Read/Update/Delete)
│ │ ├── __init__.py
│ │ ├── base.py # 基础CRUD(通用增删改查,复用)
│ │ ├── crud_user.py # 用户数据操作
│ │ └── crud_item.py # 商品数据操作
│ ├── models/ # 数据模型(数据库模型、ORM映射)
│ │ ├── __init__.py
│ │ ├── base.py # 基础模型(如带id、create_time的基类)
│ │ ├── user.py # 用户数据库模型
│ │ └── item.py # 商品数据库模型
│ ├── schemas/ # 数据校验/序列化(Pydantic模型)
│ │ ├── __init__.py
│ │ ├── base.py # 基础Schema(如分页参数、响应基类)
│ │ ├── user.py # 用户的请求/响应Schema(如登录请求、用户信息响应)
│ │ └── item.py # 商品的请求/响应Schema
│ └── services/ # 业务服务(复杂逻辑封装,跨CRUD调用)
│ ├── __init__.py
│ ├── user_service.py # 用户业务(如“注册+发送欢迎邮件”)
│ └── item_service.py # 商品业务(如“创建商品+扣库存”)
├── utils/ # 工具函数(通用工具,无业务逻辑)
│ ├── __init__.py
│ ├── auth.py # 认证工具(JWT生成/验证、密码加密)
│ ├── email.py # 邮件工具(发送邮件)
│ └── common.py # 通用工具(如时间格式化、数据转换)
├── db/ # 数据库连接层(与数据库交互的基础)
│ ├── __init__.py
│ ├── session.py # 数据库会话(创建SQLAlchemy Session)
│ └── base.py # 数据库基础(如引擎配置、Base类)
└── tests/ # 测试用例(按模块拆分,保证代码质量)├── __init__.py├── conftest.py # 测试配置(如测试数据库连接、夹具)├── test_api/ # 接口测试│ ├── test_user_api.py│ └── test_item_api.py└── test_app/ # 业务逻辑测试├── test_crud_user.py└── test_user_service.py
二、各目录核心职责说明
1. 根目录(your_project/
)
- 入口文件:
main.py
是服务启动的唯一入口,负责初始化FastAPI实例、注册路由、挂载中间件等,不包含业务逻辑。
示例(main.py
):from fastapi import FastAPI from core.config import settings from core.middlewares import add_middlewares from api.api_v1.router import api_routerapp = FastAPI(title=settings.PROJECT_NAME, version="1.0.0")# 注册中间件 add_middlewares(app)# 注册路由(统一前缀/api/v1) app.include_router(api_router, prefix=settings.API_V1_STR)if __name__ == "__main__":import uvicornuvicorn.run("main:app", host="0.0.0.0", port=settings.SERVER_PORT, reload=settings.DEBUG)
- 依赖管理:推荐用
pyproject.toml
+Poetry
(现代Python依赖管理工具),替代传统的requirements.txt
,支持虚拟环境隔离和依赖锁定。
2. 核心配置层(core/
)
- 存放全局通用、无业务关联的配置,是项目的“基础设施”,不依赖其他模块(避免循环导入)。
- 关键文件:
config.py
:用pydantic-settings
读取环境变量,统一管理配置(如数据库地址、JWT密钥、服务端口),示例:from pydantic_settings import BaseSettings, SettingsConfigDictclass Settings(BaseSettings):PROJECT_NAME: str = "FastAPI Project"API_V1_STR: str = "/api/v1"SERVER_PORT: int = 8000DEBUG: bool = False# 数据库配置DB_URL: str = "postgresql://user:password@localhost:5432/dbname"model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")settings = Settings() # 单例,全局复用
3. 接口层(api/
)
- 职责:仅负责“路由注册”和“请求/响应转换”,不包含业务逻辑(业务逻辑交给
app/services/
)。 - 版本控制:通过
api_v1/
、api_v2/
目录实现API版本共存,避免接口迭代影响旧用户。 - 路由拆分:按业务模块拆分
endpoints/
(如user.py
、item.py
),每个文件只处理对应模块的接口,示例(api/api_v1/endpoints/user.py
):from fastapi import APIRouter, Depends from app.schemas.user import UserCreate, UserResponse from app.services.user_service import create_user from api.deps.user_deps import get_current_userrouter = APIRouter(tags=["users"]) # tags用于接口文档分组@router.post("/users", response_model=UserResponse, summary="创建用户") def create_new_user(user_data: UserCreate):return create_user(user_data=user_data)@router.get("/users/me", response_model=UserResponse, summary="获取当前用户信息") def get_current_user_info(current_user: UserResponse = Depends(get_current_user)):return current_user
4. 业务逻辑层(app/
)
- 核心中的核心,与接口层解耦(即使更换接口框架,业务逻辑可复用),按功能拆分为4个子模块:
子模块 | 职责说明 |
---|---|
models/ | 数据库模型(ORM层),用SQLAlchemy定义表结构,仅描述“数据存储格式”。 |
schemas/ | 数据校验/序列化(Pydantic层),描述“接口请求/响应格式”,负责数据合法性校验。 |
crud/ | 数据操作层,封装“单一表的增删改查”,不包含复杂业务逻辑(如“只查用户,不处理权限”)。 |
services/ | 业务服务层,封装“复杂业务逻辑”(跨表操作、多步骤流程),如“注册用户=创建用户(crud)+发送邮件(utils)”。 |
- 关键原则:
crud/
只做“单表操作”,services/
做“业务组合”,避免crud/
中混入业务逻辑。
5. 工具层(utils/
)
- 存放通用工具函数,无业务关联,可跨项目复用(如密码加密、邮件发送、JWT生成)。
- 示例(
utils/auth.py
):from datetime import datetime, timedelta from jose import jwt from core.config import settings from passlib.context import CryptContextpwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")def verify_password(plain_password: str, hashed_password: str) -> bool:"""验证密码"""return pwd_context.verify(plain_password, hashed_password)def create_access_token(subject: str) -> str:"""生成JWT Token"""expire = datetime.utcnow() + timedelta(minutes=30)to_encode = {"exp": expire, "sub": subject}return jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
6. 数据库层(db/
)
- 封装数据库连接逻辑,提供“会话(Session)”供
crud/
使用,避免重复创建连接。 - 示例(
db/session.py
):from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from core.config import settings# 创建数据库引擎 engine = create_engine(settings.DB_URL, echo=settings.DEBUG)# 创建会话工厂(每次请求生成一个新Session) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)# 数据库基础类(所有models继承此类) Base = declarative_base()def get_db():"""依赖函数:获取数据库Session(请求结束自动关闭)"""db = SessionLocal()try:yield dbfinally:db.close()
7. 测试层(tests/
)
- 按“接口测试”和“业务逻辑测试”拆分,保证代码正确性和可维护性。
- 用
pytest
框架,通过conftest.py
提供测试夹具(如测试数据库Session、测试用户Token),示例(tests/test_api/test_user_api.py
):def test_create_user(client):"""测试创建用户接口"""response = client.post("/api/v1/users",json={"username": "test", "email": "test@example.com", "password": "123456"})assert response.status_code == 200assert response.json()["username"] == "test"
三、架构扩展建议
1. 大型项目(百人团队/多领域)
若项目涉及多个独立领域(如“用户系统”“订单系统”“支付系统”),可按领域拆分目录,进一步降低耦合:
your_project/
├── main.py
├── core/ # 全局核心(不变)
├── api/ # 接口层(不变)
├── domains/ # 领域层(按业务领域拆分)
│ ├── user/ # 用户领域(包含该领域的models、crud、services)
│ │ ├── models.py
│ │ ├── crud.py
│ │ └── services.py
│ ├── order/ # 订单领域
│ │ ├── models.py
│ │ ├── crud.py
│ │ └── services.py
│ └── payment/ # 支付领域
├── utils/ # 工具层(不变)
└── db/ # 数据库层(不变)
2. 新增功能模块
当需要新增一个“商品评论”模块时,只需按以下步骤操作,符合“开闭原则”:
- 在
api/api_v1/endpoints/
新增comment.py
(注册评论相关路由); - 在
app/models/
新增comment.py
(评论数据库模型); - 在
app/schemas/
新增comment.py
(评论请求/响应Schema); - 在
app/crud/
新增crud_comment.py
(评论数据操作); - 在
app/services/
新增comment_service.py
(评论业务逻辑); - 在
tests/
新增对应测试用例。
四、核心设计原则
- 分层清晰:接口层(api)→ 业务层(app)→ 数据层(db),每一层只做自己的事,避免“一锅粥”。
- 依赖单向:底层模块(core、utils、db)不依赖上层模块(api、app),避免循环导入。
- 配置中心化:所有配置通过
core/config.py
读取,不硬编码(如数据库地址、密钥)。 - 可测试性:业务逻辑与接口解耦,便于单独测试(如直接测试
services
,无需启动服务)。
通过以上架构,FastAPI项目可以轻松应对需求迭代,同时保持代码的可读性和可维护性,可以说是目前工业界验证过的“最佳实践”之一。