在FastAPI开发中,很多新手会陷入“单文件走天下”的误区——用一个main.py搞定所有路由、模型、业务逻辑,快速实现功能确实便捷,但随着项目迭代,代码量激增、逻辑混乱、维护困难等问题会逐渐凸显。
好的项目目录结构,就像一套规整的“代码收纳系统”,既能让开发者快速定位所需代码,也能提升项目的可维护性、可扩展性,更能适配生产环境的协作开发需求。无论是中小型API服务,还是复杂微服务,一套规范的目录结构都是必不可少的。
今天,我们就专门聊聊FastAPI项目的目录结构设计,从新手友好的简化版,到适配生产的标准版,详细拆解每个目录的作用、使用场景,帮你摆脱代码混乱的困扰,实现优雅规范的FastAPI开发。
一、为什么要重视FastAPI目录结构?
在回答“怎么设计目录”之前,我们先搞清楚“为什么需要规范目录”。很多新手觉得“只要功能能实现,目录怎么放都无所谓”,但在实际开发中,不规范的目录会带来诸多麻烦:
- 维护成本高:单文件代码量动辄上千行,找一个路由、改一个模型都要翻半天,后续迭代时极易出错;
- 协作困难:多人开发时,大家代码风格、存放位置不一,容易出现冲突,沟通成本飙升;
- 扩展性差:新增功能时,只能在原有文件中“塞代码”,导致代码耦合度极高,后续拆分、重构难度极大;
- 生产适配难:不规范的目录无法适配生产环境的部署、测试、日志管理等需求,从开发到生产的过渡会异常繁琐。
而规范的目录结构,能完美解决这些问题——它将代码按功能模块拆分,实现“职责单一、解耦清晰”,无论是单人开发还是团队协作,都能快速上手,同时也能无缝适配生产环境的各项要求。对于FastAPI这类主打“高效、规范”的框架而言,规范的目录结构更是发挥其优势的基础。
二、新手入门:简化版目录结构(快速上手)
对于新手练习、小型demo或简单接口开发,无需追求复杂的目录结构,简化版足以满足需求。这种结构核心是“少而精”,减少不必要的目录层级,让新手能专注于功能实现,后续再逐步扩展。
1. 简化版目录结构(可直接复用)
fastapi_demo/ # 项目根目录
├── main.py # 入口文件(核心代码统一存放)
├── requirements.txt # 项目依赖清单
└── tests.py # 测试文件(简单接口测试)
2. 各文件核心作用
- main.py:项目的核心入口,初始化FastAPI应用、定义路由、模型(Pydantic/ORM)、依赖项等,所有核心逻辑暂时放在这里,适合代码量较少的场景。比如我们之前写的SQLModel实战案例,新手阶段可以将所有代码都放在main.py中,快速实现CRUD接口。
- requirements.txt:记录项目所有依赖包及版本,方便他人复用项目时快速安装依赖。比如fastapi、uvicorn、sqlmodel等,格式为“包名==版本号”,避免因版本兼容问题导致项目无法运行。
- tests.py:存放接口测试代码,利用FastAPI内置的TestClient,快速测试路由接口的正确性,避免手动测试的繁琐,也能确保后续修改代码后,接口功能不受影响。
3. 适用场景
新手练习、单个简单接口开发、快速原型验证(比如1-2个接口的小demo),无需复杂的模块拆分,简化版目录能让你快速上手,专注于FastAPI的核心用法,不用被目录结构分心。
三、生产适配:标准版目录结构(推荐首选)
当项目规模扩大、需要团队协作,或者要部署到生产环境时,简化版目录就无法满足需求了。此时,我们需要一套标准化的目录结构,按功能模块拆分代码,实现解耦,适配生产环境的各项要求。以下是FastAPI官方推荐、行业通用的标准目录结构,适配中小型API服务和微服务场景,可直接复用。
1. 标准目录结构(完整版)
fastapi_project/ # 项目根目录
├── app/ # 核心应用目录(所有业务代码存放于此)
│ ├── __init__.py # 标记为Python包,可空文件
│ ├── main.py # 项目入口,初始化FastAPI应用、注册路由
│ ├── api/ # 路由目录(按业务模块拆分)
│ │ ├── __init__.py
│ │ ├── items.py # 商品相关路由(如/items/)
│ │ └── users.py # 用户相关路由(如/users/)
│ ├── models/ # 数据模型目录(Pydantic模型、ORM模型)
│ │ ├── __init__.py
│ │ ├── schemas.py # Pydantic模型(请求体、响应体校验/序列化)
│ │ └── orm.py # ORM模型(与数据库交互,如SQLModel/SQLAlchemy)
│ ├── dependencies.py # 依赖项目录(权限验证、数据库会话等)
│ ├── crud/ # 数据操作目录(增删改查逻辑封装)
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── utils/ # 工具函数目录(日志、异常处理等通用工具)
│ ├── __init__.py
│ ├── logger.py # 日志配置
│ └── exceptions.py # 自定义异常处理
├── requirements.txt # 项目依赖清单(fastapi、uvicorn等)
├── .env # 环境变量配置(敏感信息,不提交到Git)
├── .env.example # 环境变量示例(提交到Git,供他人参考)
├── tests/ # 测试目录(按模块拆分测试用例)
│ ├── __init__.py
│ ├── test_items.py
│ └── test_users.py
└── README.md # 项目说明文档(部署、启动、接口说明等)
2. 各目录/文件核心作用(重点详解)
标准目录的核心思路是“职责单一、解耦清晰”,每个目录都有明确的定位,避免代码混乱,下面逐个拆解核心目录的作用,帮你快速理解如何使用。
(1)app/:核心应用目录
所有业务代码的核心存放目录,相当于项目的“心脏”,里面包含了FastAPI应用的所有核心组件,也是我们日常开发中最常操作的目录。
app/main.py:项目入口
整个FastAPI应用的入口文件,主要负责3件事:
- 初始化FastAPI应用,配置项目标题、版本、描述、文档地址等元信息;
- 通过
include_router批量注册api目录下的所有路由,避免在main.py中写大量路由代码; - 配置中间件(如CORS跨域、日志中间件)、启动事件(如应用启动时创建数据库表)等全局配置。
示例代码(main.py核心内容):
from fastapi import FastAPI
from app.api.users import user_router
from app.api.items import item_router
from app.dependencies import create_db_and_tables
# 初始化FastAPI应用
app = FastAPI(
title="FastAPI标准项目",
description="基于标准目录结构的FastAPI服务",
version="1.0.0",
docs_url="/docs", # 自定义Swagger文档地址
redoc_url="/redoc"
)
# 注册路由(批量导入api目录下的路由)
app.include_router(user_router, prefix="/users", tags=["用户管理"])
app.include_router(item_router, prefix="/items", tags=["商品管理"])
# 应用启动时执行(创建数据库表)
@app.on_event("startup")
def on_startup():
create_db_and_tables()
app/api/:路由目录(按业务模块拆分)
这是路由的集中管理目录,核心是“按业务模块拆分路由”,避免单文件路由过多,提升可维护性。比如用户管理、商品管理是两个不同的业务模块,分别放在users.py和items.py中,互不干扰。
每个路由文件中,通过APIRouter定义该模块的路由,再在main.py中批量注册,实现路由的模块化管理。
示例代码(app/api/users.py):
from fastapi import APIRouter, Depends
from app.models.schemas import UserCreate, UserResponse
from app.crud.users import create_user, get_user
from app.dependencies import get_db_session
# 定义用户模块路由
user_router = APIRouter()
# 创建用户(POST接口)
@user_router.post("/", response_model=UserResponse, status_code=201)
def create_user_api(user: UserCreate, db=Depends(get_db_session)):
return create_user(db, user)
# 查询单个用户(GET接口)
@user_router.get("/{user_id}", response_model=UserResponse)
def get_user_api(user_id: int, db=Depends(get_db_session)):
return get_user(db, user_id)
app/models/:数据模型目录
专门存放数据模型,核心是区分“Pydantic模型”和“ORM模型”,实现数据验证与数据存储的解耦,这也是FastAPI规范开发的关键。
- schemas.py:存放Pydantic模型,用于API接口的请求体、响应体验证和序列化。比如用户创建时的请求体(需要验证用户名、邮箱格式)、接口返回的响应体(指定返回哪些字段),都在这里定义。
- orm.py:存放ORM模型(如SQLModel、SQLAlchemy模型),用于与数据库交互,定义数据库表结构、字段类型、关联关系等。比如我们之前实战中定义的User、Order模型,就放在这里。
这种拆分的好处是:当需要修改接口请求/响应格式时,只需修改schemas.py;当需要修改数据库表结构时,只需修改orm.py,互不影响,降低耦合度。
app/dependencies.py:依赖项目录
存放所有通用依赖项,实现代码复用和解耦。依赖项是FastAPI的核心特性之一,比如数据库会话、权限验证、日志记录等通用逻辑,都可以抽取到这里,在需要的路由中通过Depends注入,无需重复编写代码。
示例代码(dependencies.py核心内容):
from sqlmodel import Session, create_engine
from app.models.orm import SQLModel
from fastapi import Depends, HTTPException
# 数据库连接配置
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
# 依赖项1:获取数据库会话(每次请求创建一个新会话)
def get_db_session():
with Session(engine) as session:
yield session
session.close()
# 依赖项2:权限验证(模拟Token验证)
def verify_token(token: str):
if token != "fastapi_auth":
raise HTTPException(status_code=401, detail="权限不足")
return "验证通过"
# 应用启动时创建数据库表
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
app/crud/:数据操作目录
封装所有数据库操作逻辑(增删改查),避免在路由函数中写大量业务代码,实现“路由与业务逻辑解耦”。比如创建用户、查询用户、更新用户等操作,都在这里定义成函数,路由函数只需调用这些函数,无需关心具体的数据库操作细节。
这种设计的好处是:业务逻辑可复用(多个路由可调用同一个CRUD函数)、便于测试(可单独测试CRUD函数,无需启动整个API服务)、便于维护(修改数据库操作逻辑时,只需修改CRUD函数)。
app/utils/:工具函数目录
存放所有通用工具函数,比如日志配置、自定义异常处理、数据格式化、加密解密等,这些工具函数不涉及具体业务逻辑,可在整个项目中复用,避免重复编码。
(2)项目根目录其他文件
- requirements.txt:记录项目所有依赖包及版本,格式为“包名==版本号”,比如
fastapi==0.103.1、uvicorn==0.23.2、sqlmodel==0.0.8,确保他人复用项目时,能安装与当前项目一致的依赖,避免版本兼容问题。 - .env:存放敏感配置信息,比如数据库URL、JWT密钥、API密钥等,这些信息不能提交到Git仓库(需在.gitignore中忽略),避免泄露。通过
python-dotenv库加载,在代码中通过os.getenv("配置项名称")获取。 - .env.example:环境变量示例文件,提交到Git仓库,供他人参考,里面只保留配置项名称,不填写具体敏感值,比如
DATABASE_URL=sqlite:///./test.db、JWT_SECRET=your_secret_key。 - tests/ :测试目录,按业务模块拆分测试用例,比如test_users.py测试用户相关接口,test_items.py测试商品相关接口。利用FastAPI内置的TestClient,可直接模拟HTTP请求,测试接口的正确性,确保项目稳定性。
- README.md:项目说明文档,是项目的“说明书”,主要包含项目介绍、启动步骤、部署方法、接口说明、注意事项等,方便他人快速了解和使用项目。
四、目录结构使用技巧与注意事项
掌握了目录结构的设计后,还有几个实用技巧和注意事项,帮你更好地运用目录结构,提升开发效率,避免踩坑。
1. 灵活调整,适配项目规模
标准目录结构并非“一成不变”,可根据项目规模灵活调整。比如:
- 小型项目:可省略utils/、dependencies.py,将相关逻辑临时放在main.py或对应模块中,后续逐步扩展;
- 大型项目:可在app/目录下新增更多子目录,比如
app/services/(业务服务层)、app/middlewares/(自定义中间件)、app/config/(配置文件目录),进一步拆分逻辑,降低耦合度。
2. 遵循“单一职责”原则
每个目录、每个文件都只负责一件事:路由文件只写路由映射,模型文件只定义模型,CRUD文件只写数据操作,工具文件只写通用工具,避免“一个文件干所有事”。
3. 统一命名规范
目录和文件命名要统一,便于团队协作和定位。比如:
- 路由文件:按业务模块命名,如users.py、items.py;
- CRUD文件:与路由文件对应,如crud/users.py、crud/items.py;
- 测试文件:以test_开头,与业务模块对应,如test_users.py、test_items.py。
4. 不要忽略.gitignore文件
在项目根目录添加.gitignore文件,忽略不需要提交到Git仓库的文件,比如.env、pycache/、数据库文件(test.db)、虚拟环境目录(venv/)等,避免敏感信息泄露和冗余文件提交。
5. 结合ORM实战,规范目录使用
结合我们之前的SQLModel实战案例,将代码按标准目录拆分:
- ORM模型(User、Order)放在app/models/orm.py;
- 请求体/响应体模型(如UserCreate、UserResponse)放在app/models/schemas.py;
- 用户相关CRUD操作放在app/crud/users.py;
- 用户相关路由放在app/api/users.py;
- 数据库会话依赖放在app/dependencies.py。
这样拆分后,代码结构清晰,后续新增功能、修改逻辑时,能快速定位到对应文件,大幅提升维护效率。
五、总结:规范目录,让FastAPI开发更优雅
FastAPI的核心优势是“高效、规范、易用”,而规范的目录结构,正是发挥这些优势的基础。从新手入门的简化版目录,到适配生产的标准版目录,本质上是“从快速实现到规范可维护”的过渡,也是每个开发者成长的必经之路。
总结一下核心要点:
- 新手阶段:用简化版目录快速上手,专注功能实现,不用纠结复杂结构;
- 生产阶段:用标准版目录,按“路由、模型、CRUD、依赖、工具”拆分代码,实现解耦;
- 核心原则:职责单一、命名规范、灵活调整,适配项目规模和团队协作需求。
一套规范的目录结构,不仅能让你的代码更整洁、更易维护,也能让你在团队协作和生产部署中少走弯路。无论是开发小型API,还是复杂微服务,都建议从一开始就养成规范目录的习惯,让FastAPI开发更优雅、更高效。
后续,我们可以基于这套标准目录结构,结合SQLModel、依赖注入、权限认证等功能,搭建一个完整的生产级FastAPI项目,真正实现“规范开发、无缝部署”。