FastAPI 中 Pydantic 模型与 SQLAlchemy ORM 模型的分工与转换规范

一、核心定义

  • Pydantic 模型 :数据校验与序列化层。继承自 pydantic.BaseModel,定义数据结构、字段类型及校验规则(如长度、正则、取值范围)。与数据库无关。

  • SQLAlchemy ORM 模型 :数据库映射层。继承自 sqlalchemy.orm.DeclarativeBase 生成的基类(Base),定义表名(__tablename__)、字段列(Column)及关系映射。与数据库表结构直接绑定。


二、核心差异对比表

维度 Pydantic 模型 SQLAlchemy ORM 模型
导入基类 from pydantic import BaseModel from sqlalchemy.orm import DeclarativeBase(或 declarative_base())
字段定义 name: str(类型注解) name = Column(String(30))(列对象)
核心职责 1. 反序列化(JSON → Python 对象) 2. 数据校验 3. 序列化(Python 对象 → JSON) 1. 映射数据库表结构 2. 管理行数据(Row)与 Python 对象的转换 3. 配合 Session 执行 SQL
FastAPI 参数注入 原生支持 (@app.post 中自动解析请求体 JSON) 不支持(ORM 对象含有数据库元数据,无法由 JSON 直接反序列化)
数据库操作 无法直接用于 db.add() 或 db.execute() 专用于 db.add() 和 db.execute(select(Model))
序列化兼容性 默认支持 .model_dump() 转换为字典 / JSON 直接返回给 FastAPI 时可能引发循环引用或包含无用元数据(不推荐)

三、使用场景划分(黄金准则)

1. 接口参数(接收前端数据)------ 必须使用 Pydantic

python 复制代码
@app.post("/users")
async def create_user(user_data: UserCreate):  # UserCreate 继承 BaseModel
    ...

原因:FastAPI 通过 Pydantic 完成 JSON 解析、类型强制转换及业务规则校验。

2. 数据库操作(增删改查)------ 必须使用 ORM 模型

python 复制代码
new_user = User(name="张三")   # User 继承 Base(ORM)
db.add(new_user)
await db.commit()

原因 :ORM 模型持有 __tablename__ 及列映射信息,是 SQLAlchemy 生成 SQL 语句的唯一依据。

3. 接口返回值(返回数据给前端)------ 优先使用 Pydantic

python 复制代码
@app.get("/users/{id}")
async def get_user(id: int) -> UserOut:  # UserOut 继承 BaseModel
    ...

原因:

  • 字段隐藏 :过滤敏感字段(如密码哈希值 hashed_password)。

  • 结构稳定:避免 ORM 模型的延迟加载(Lazy Loading)在序列化时触发额外查询(N+1 问题)或报错。

  • 文档生成:Pydantic 模型能自动生成清晰的 OpenAPI 响应结构。


四、两者转换方法(强制记忆代码块)

前端传入的是 Pydantic 对象 ,数据库需要的是 ORM 对象 。反之亦然。转换必须由开发者显式编写。

转换 1:Pydantic → ORM(入库前)

python 复制代码
# 使用 model_dump() 提取字典(Pydantic v2 标准方法)
orm_obj = User(**pydantic_obj.model_dump())

# 若 Pydantic 字段名与 ORM 字段名不完全一致,可用 model_dump(exclude_unset=True) 控制

转换 2:ORM → Pydantic(返回前)

python 复制代码
# 使用 model_validate() 自动提取 ORM 对象的属性(支持 ORM 对象模式)
pydantic_obj = UserOut.model_validate(orm_obj)

注意 :model_validate 默认会读取 ORM 对象的 __dict__ 属性,若存在延迟加载字段未填充,需确保 select 查询时已加载,或使用 joinedload() 预加载。


五、项目分层目录规范(推荐)

为了杜绝混淆,建议严格按文件划分职责:

文件名 包含内容 目标
database.py engine、AsyncSessionLocal、get_db 依赖、Base 基类 连接管理与基础架构
models.py class User(Base): 等(定义 __tablename__ 和 Column) ORM 模型层(仓库蓝图)
schemas.py class UserCreate(BaseModel):、class UserOut(BaseModel): 等 Pydantic 层(接口契约)
routers.py 或 crud.py 接口逻辑,包含 Pydantic ↔ ORM 的显式转换 业务胶水层
相关推荐
一枕槐安4872 分钟前
应届生 RAG 项目包装:FastAPI 检索服务接口设计指南
fastapi·web服务·rag·pydantic·接口封装
又蓝1 天前
【元宝搜索开发者征文大赛】用 FastAPI + Vue3 做了个 AI 炒股工具,接了六个分析师和腾讯元宝搜索
人工智能·python·ai·fastapi
外收内放1 天前
FastAPI猜字谜实战(8):收官
开发语言·python·学习·fastapi
hhb_6182 天前
FastAPI接口开发与性能优化实战
性能优化·fastapi
程序猿乐锅2 天前
【从0-1学习Python | 第九篇】继承
开发语言·后端·python·学习·fastapi
外收内放3 天前
FastAPI猜字谜实战(4):让AI主持人开口
开发语言·python·学习·fastapi
外收内放3 天前
FastAPI猜字谜实战(6):日志与异常
开发语言·python·学习·fastapi
小林ixn3 天前
用 FastAPI + SQLAlchemy 从零手搓一个博客系统:一套能落地、能讲清楚的 RESTful 后端
后端·python·fastapi
外收内放3 天前
FastAPI猜字谜实战(5):会话管理
开发语言·python·学习·fastapi
Sakura_j_h_4 天前
给 FastAPI 接大模型:超时、重试和 token 成本该怎么管
python·大模型·fastapi·超时重试·token计费