介绍
企业级 FastAPI+SQLAlchemy2.0 开发核心要求:模块化、可维护、可扩展、符合生产规范、支持团队协作。我给你一套工业级标准架构(最通用、大厂最常用),直接可落地。
目录结构
your_project/
├── .env # 环境变量配置
├── .env.example
├── .gitignore
├── data/ # 存放SQLite db、上传文件、临时数据
│ └── db.sqlite3
├── sql/ # 存放初始化SQL、种子SQL、升级SQL
│ ├── init.sql
│ └── seed.sql
├── alembic/ # 数据库迁移
├── app/
│ ├── api/ # 控制器层 Controller
│ │ ├── v1/ # 接口版本 v1
│ │ ├── deps.py # 全局依赖(DB、登录、权限)
│ │ └── api.py # 总路由入口
│ ├── core/ # 核心配置
│ │ ├── config.py # 项目配置(.env)
│ │ ├── security.py # JWT、密码加密
│ │ ├── exceptions.py # 全局异常处理
│ │ └── response.py # 统一返回格式
│ ├── db/ # 数据库连接
│ │ ├── base.py # ORM 基类
│ │ └── session.py # DB 会话
│ ├── models/ # 数据库实体 Entity
│ ├── schemas/ # 请求/响应 DTO
│ ├── services/ # 业务逻辑 Service
│ ├── crud/ # 数据访问 DAO
│ └── main.py # 项目入口
├── requirements.txt # 依赖
└── run.py # 启动脚本
为什么创建 app 子目录
为了:把【业务代码】和【项目配置/文件】彻底分开!**
- 工程根目录 = 只放配置、数据库、上传文件、工具
- app/ = 只放代码
创建 app 目录的目的
1. 代码 vs 数据 分离(最重要!)
app/:纯代码(接口、模型、逻辑、工具)- 根目录:数据/配置(数据库、上传文件、.env、pyproject.toml)
这样做的好处:
- 备份代码时,不用带上 GB 级的数据库和上传文件
- 不会把业务文件不小心提交到 Git
- 代码干净,不污染
2. 让项目变成「Python 包」
创建 app/ + __init__.py
你的项目就变成了一个标准 Python 包:
from app.config import settings
from.app.api.upload import router
导入清晰、不乱、不报错
这是大型项目必须的。
3. 方便内部模块化
app/
├── api/ # 接口
├── models/ # 数据库模型
├── core/ # 核心逻辑
├── utils/ # 工具
不用翻来翻去,结构一目了然。
4. 为未来扩展做准备
为扩展准备: 让当前项目本身能无限变大!
对比
❌ 不建 app/(混乱)
your-project/
main.py
config.py
database.py
upload/
db.sqlite3
.env
pyproject.toml
文件堆在一起,大了必乱。
✅ 建 app/(标准、干净、可扩展)
your-project/
# 根目录:配置 + 数据 + 环境
db.sqlite3
upload/
.env
pyproject.toml
# app/:只放代码
app/
main.py
config.py
api/
models/
core/
建议
- 练手、小项目:不要建 app 文件夹,直接根目录平铺。
- 写正式项目、找工作:一定要用 app 分层结构。
- 数据库文件永远放data/,不要丢根目录。
- .env永远放根目录,不要塞进app里面。
- 路由不写业务、业务不写SQL,严格分层。
分层架构
和 Java SSM / SpringBoot 完全对应:
| Python 层 | Java 对应 | 职责 |
|---|---|---|
| api/ | Controller | 接收请求、参数校验、返回响应 |
| schemas/ | DTO/VO | 请求体、响应体格式 |
| services/ | Service | 业务逻辑、事务、规则 |
| crud/ | DAO/Mapper | 数据库增删改查 |
| models/ | Entity | 数据库表结构 |
| db/ | 数据源配置 | 数据库连接 |
| core/ | 配置/工具 | 全局配置、异常、安全 |
请求流程(标准)
请求 → API 路由 → 依赖验证 → Service 业务 → CRUD 数据库 → 返回响应
绝对不允许:
- API 里写业务逻辑
- Service 里写原生 SQL
- Controller 直接操作数据库
命名规范
目录命名
- 全部小写
- 单词之间不用分隔符(api / core / services)
- 复数优先:models / schemas / services / crud
- 版本号固定:v1 / v2 / v3(小写)
文件命名规范
通用规则
- 全部小写
- 多单词用下划线
_分隔 - 禁止空格、横杠、中文、大写字母
api/ 控制器层
api/
├── v1/
│ ├── __init__.py
│ ├── user_api.py # 用户接口
│ ├── auth_api.py # 认证接口
│ ├── order_api.py # 订单接口
│ └── admin_api.py # 管理后台接口
命名:业务名_api.py
接口 URL 命名规范(RESTful 企业标准)
- 小写
- 复数资源
- 下划线分隔
- 版本号在前
/api/v1/users
/api/v1/users/{user_id}
/api/v1/orders
/api/v1/auth/login
/api/v1/auth/logout
统一返回格式(企业标准)
{
"code": 200, // 业务状态码
"msg": "成功", // 消息
"data": {} // 数据
}
services/ 业务层
services/
├── __init__.py
├── user_service.py
├── auth_service.py
└── order_service.py
命名:业务名_service.py
crud/ 数据访问层
crud/
├── __init__.py
├── user_crud.py
├── order_crud.py
└── product_crud.py
命名:业务名_crud.py
models/ 模型层
models/
├── __init__.py
├── user.py
├── role.py
├── order.py
└── product.py
命名:单数、小写、下划线:user.py / order.py
core/ 核心层
core/
├── config.py # 固定
├── security.py # 固定
├── exceptions.py # 固定
└── response.py # 固定
db/ 数据库层
db/
├── base.py # 固定:ORM 基类
└── session.py # 固定:数据库会话
schemas/ DTO 层
schemas/
├── __init__.py
├── user_schema.py
├── auth_schema.py
└── order_schema.py
命名:业务名_schema.py
类命名规范
1. ORM 模型(models)
- 大驼峰(UpperCamelCase)
- 单数
- 名词
# models/user.py
class User(Base):
__tablename__ = "users" # 表名:复数、小写、下划线
class Order(Base):
__tablename__ = "orders"
2. Pydantic Schema(schemas)
# 用户创建请求 DTO
class UserCreate(BaseModel):
username: str
password: str
# 用户响应 DTO
class UserResp(BaseModel):
id: int
username: str
规则:
- 请求:
UserCreate/OrderCreate - 响应:
UserResp/OrderResp - 更新:
UserUpdate
3. Service 业务类
class UserService:
def get_user_by_id(self, user_id: int):
...
命名:业务名 + Service
4. CRUD 数据访问类
class UserCRUD:
def get(self, db: Session, id: int):
...
命名:业务名 + CRUD
函数/方法命名
通用规则
- 小写 + 下划线
- 动词开头
- 见名知意
1. Controller 接口函数
@router.get("/users/{user_id}")
def get_user(user_id: int): ...
@router.post("/users")
def create_user(user_in: UserCreate): ...
2. Service 业务函数
def get_user_by_id(db: Session, user_id: int): ...
def create_user(db: Session, user_in: UserCreate): ...
def check_user_permission(db: Session, user_id: int): ...
3. CRUD 函数(标准模板)
def get(db: Session, id: int): ... # 单条查询
def get_list(db: Session): ... # 列表
def create(db: Session, obj_in): ... # 创建
def update(db: Session, db_obj, obj_in): ...# 更新
def delete(db: Session, id: int): ... # 删除
变量/常量命名
1. 变量
- 小写 + 下划线
user_info user_list current_user access_token
2. 常量(core/config.py)
- 全部大写 + 下划线
SECRET_KEY ACCESS_TOKEN_EXPIRE_MINUTES DATABASE_URL REDIS_URL
案例
下面以添加用户、查找用户为例实现代码
1. app/core/config.py 配置
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
API_PREFIX: str = "/api/v1"
DB_URL: str = "mysql+pymysql://root:123456@localhost:3306/fastapi"
JWT_SECRET: str = "my-secret"
JWT_ALGORITHM: str = "HS256"
settings = Settings()
2. app/db/session.py 数据库连接
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.core.config import settings
engine = create_engine(settings.DB_URL, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
3. app/db/base.py ORM 基类
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
4. app/models/user.py 模型(Entity)
from sqlalchemy import Column, Integer, String
from app.db.base import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True)
email = Column(String(100))
hashed_password = Column(String(255))
5. app/schemas/user.py DTO
from pydantic import BaseModel, EmailStr
class UserCreate(BaseModel):
username: str
email: EmailStr
password: str
class UserResp(BaseModel):
id: int
username: str
email: str
class Config:
orm_mode = True
6. app/crud/user.py DAO
from sqlalchemy.orm import Session
from app.models.user import User
from app.schemas.user import UserCreate
def create_user(db: Session, user: UserCreate, hashed_pwd: str):
db_user = User(username=user.username, email=user.email, hashed_password=hashed_pwd)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
def get_user(db: Session, user_id: int):
return db.query(User).filter(User.id == user_id).first()
7. app/services/user_service.py Service
from sqlalchemy.orm import Session
from app.crud import user as user_crud
from app.schemas.user import UserCreate
from app.core.security import get_password_hash
from fastapi import HTTPException
class UserService:
@staticmethod
def create_user(db: Session, user_in: UserCreate):
# 业务逻辑:检查用户名是否存在
hashed_pwd = get_password_hash(user_in.password)
return user_crud.create_user(db, user_in, hashed_pwd)
@staticmethod
def get_user(db: Session, user_id: int):
user = user_crud.get_user(db, user_id)
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
return user
8. app/api/v1/users.py Controller
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.api.deps import get_db
from app.schemas.user import UserCreate, UserResp
from app.services.user_service import UserService
router = APIRouter()
@router.post("/", response_model=UserResp)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
return UserService.create_user(db, user)
@router.get("/{user_id}", response_model=UserResp)
def get_user(user_id: int, db: Session = Depends(get_db)):
return UserService.get_user(db, user_id)
9. app/main.py 入口
from fastapi import FastAPI
from app.api.api import api_router
from app.core.config import settings
app = FastAPI(title="企业级 FastAPI 架构")
app.include_router(api_router, prefix=settings.API_PREFIX)
优势
✅ 完全解耦:API、业务、数据库三层分离
✅ 适合团队协作
✅ 可维护、可扩展、可测试
✅ 生产环境稳定
✅ SQLAlchemy 2.0 标准用法
✅ FastAPI 官方推荐架构
✅ 和 Java 架构思维一致
为什么api/有 v1
版本只对外,不对内,v1/v2 是对外接口版本,给前端/第三方调用用的
后端接口是对外暴露的:
- 前端 App、小程序、第三方系统 都在调用
- 迭代不能直接改老接口,会崩老版本客户端
- 所以要做接口版本兼容
举例:
- 老用户用旧 App 访问:
/api/v1/user - 新用户用新 App 访问:
/api/v2/user
接口地址隔离,互不影响,这就是 v1 的意义。
为什么 models / crud / service / schemas 不用加 v1?
这些是内部私有逻辑,不对外暴露
前端永远不会直接调用:
- models 数据库实体
- crud 数据库操作
- service 业务逻辑
- schemas 内部DTO
都是后端自己内部调用,没必要版本化。
内部逻辑统一维护一套即可
v1、v2 接口 共用同一套底层 models、service、crud
只在路由层做适配转发,不用重复写两套数据库、两套业务。
架构逻辑:
前端请求 → api/v1 或 api/v2 路由
↓
共用同一套 service / crud / models
避免代码冗余爆炸
如果每个版本都复制一套 models、service:
v1_models、v2_models、v1_service、v2_service……
后期维护直接崩盘,重复代码一大堆。
什么时候内部也要拆分?
只有业务完全不兼容、底层表结构都变了,才会单独拆一套内部逻辑,
但这属于新项目,不是同一个项目的 v1/v2。
总结
api/v1:对外接口版本,兼容前端老客户端- models/crud/service:内部底层,全局共用一套,不用版本
- 版本只做在入口路由层,底层统一复用,不重复造轮子