当前位置: 首页 > news >正文

FastAPI 中,数据库模型(通常使用 SQLAlchemy 定义)和接口模型(使用 Pydantic 定义的 schemas)的差异

在 FastAPI 中,数据库模型(通常使用 SQLAlchemy 定义)和接口模型(使用 Pydantic 定义的 schemas)虽然都用于表示数据结构,但它们有明确的职责区分。以下是它们的核心区别和协作方式:


1. 数据库模型 (Models)

位置:通常在 models.py 中定义
技术:使用 SQLAlchemy ORM
目的:直接映射数据库表结构,处理数据库操作
特点

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class UserDB(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(200))  # 敏感字段created_at = Column(DateTime)  # 数据库自动生成的时间戳

关键特性

  • 包含数据库特有的字段类型(如 Column
  • 定义表名、主键、索引、约束等
  • 包含敏感字段(如密码哈希)
  • 包含 ORM 关系(如 relationship
  • 可能有数据库自动生成的字段(如创建时间)

2. 接口模型 (Schemas)

位置:通常在 schemas.py 中定义
技术:使用 Pydantic BaseModel
目的:定义 API 输入/输出的数据结构
特点

from pydantic import BaseModel, EmailStrclass UserCreate(BaseModel):  # 创建用户的请求模型username: stremail: EmailStr  # 自动邮箱格式验证password: strclass UserPublic(BaseModel):  # 返回给用户的响应模型id: intusername: stremail: strclass UserPrivate(UserPublic):  # 内部使用的扩展模型hashed_password: str

关键特性

  • 使用 Python 原生类型(str, int 等)
  • 内置数据验证(如 EmailStr
  • 可定义不同场景的模型(创建/响应/更新)
  • 不包含数据库技术细节
  • 可配置响应排除敏感字段

3. 核心区别对比表

特性数据库模型 (Models)接口模型 (Schemas)
职责数据库表映射API 数据验证和序列化
技术SQLAlchemy ORMPydantic
字段类型Column(Integer)Python 原生类型 (int, str)
敏感字段包含密码等敏感信息通常排除敏感字段
关系处理直接定义 relationship通过嵌套模型表示
自动生成字段包含 (如 created_at)通常不包含
数据验证基础约束 (如 unique=True)高级验证 (正则、邮箱格式等)

4. 协作流程示例

用户注册场景:
客户端FastAPI 路由Pydantic 模型数据库模型数据库POST /users (JSON: {username, email, password})用 UserCreate 验证输入验证通过的数据转换 UserCreate → UserDB 模型执行 INSERT 操作返回创建的数据库对象转换 UserDB → UserPublic 模型序列化为 JSON返回 201 Created (UserPublic)客户端FastAPI 路由Pydantic 模型数据库模型数据库
代码实现:
# schemas.py
class UserCreate(BaseModel):username: stremail: EmailStrpassword: strclass UserPublic(BaseModel):id: intusername: stremail: str# models.py
class UserDB(Base):__tablename__ = "users"id = Column(Integer, primary_key=True)username = Column(String(50), unique=True)email = Column(String(100))hashed_password = Column(String(200))# crud.py
def create_user(db: Session, user: schemas.UserCreate):# 转换并处理密码hashed_pw = hash_password(user.password)# 创建数据库模型db_user = models.UserDB(username=user.username,email=user.email,hashed_password=hashed_pw)db.add(db_user)db.commit()return db_user# main.py
@app.post("/users", response_model=schemas.UserPublic)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):db_user = crud.create_user(db, user)return db_user  # 自动转换为 UserPublic

5. 为什么需要分离?

  1. 安全隔离

    • 数据库模型包含敏感字段(如密码哈希)
    • 接口模型可排除敏感字段(通过 response_model
  2. 职责分离

    • 数据库模型关注存储结构
    • 接口模型关注API契约
  3. 灵活性

    # 同一个数据库模型对应多个接口模型
    class UserUpdate(BaseModel):  # 更新专用模型email: Optional[EmailStr]password: Optional[str]
    
  4. 验证与约束解耦

    • 数据库约束:唯一索引、外键关系
    • API验证:邮箱格式、密码强度
  5. 避免技术泄露

    • 接口模型不暴露数据库技术细节(如 SQLAlchemy 类型)
    • 保持 API 的稳定性和可替换性

最佳实践建议

  1. 单向依赖
    Schemas 应该 不依赖 Models,保持解耦

  2. 转换层
    在路由和 CRUD 操作之间进行模型转换:

    # 在路由处理函数中
    db_user = UserDB(**user_create.dict())
    
  3. 使用 orm_mode
    使 Pydantic 能直接处理 ORM 对象:

    class UserPublic(BaseModel):class Config:orm_mode = True  # 允许从ORM对象创建
    
  4. 分层设计

    app/
    ├── models.py    # SQLAlchemy 模型
    ├── schemas.py   # Pydantic 模型
    ├── crud.py      # 数据库操作(使用 models)
    └── api.py       # 路由(使用 schemas 和 crud)
    

这种分离设计使得 FastAPI 应用能够:

  • 安全地处理敏感数据
  • 独立演化数据库和API
  • 提供清晰的API文档(通过Pydantic自动生成)
  • 保持代码的可维护性和可测试性
http://www.lryc.cn/news/595332.html

相关文章:

  • Excel函数 —— TEXTJOIN 文本连接
  • 系统分析师-计算机系统-操作系统-存储器管理设备管理
  • LeafletJS 插件开发:扩展自定义功能
  • Java 实现 TCP 一发一收通信
  • 力扣面试150题--搜索二维矩阵
  • A316-Mini-V1:超小尺寸USB高清音频解码器模组技术探析
  • 解决 Ant Design v5.26.5 与 React 19.0.0 的兼容性问题
  • macOS 上安装 Kubernetes(k8s)
  • React 中使用immer修改state摆脱“不可变”
  • Ubuntu安装k8s集群入门实践-v1.31
  • HOT100——图篇Leetcode207. 课程表
  • Redis入门教程(一):基本数据类型
  • (LeetCode 每日一题) 1957. 删除字符使字符串变好 (字符串)
  • 17 BTLO 蓝队靶场 Pretium 解题记录
  • 【C++11】哈希表与无序容器:从概念到应用
  • 【Unity基础】Unity中2D和3D项目开发流程对比
  • 用户虚拟地址空间布局架构
  • git_guide
  • 【Git#6】多人协作 企业级开发模型
  • 【面经】实习经历
  • 深入理解 C++ 中的指针与自增表达式:*a++、(*a)++ 和 *++a 的区别解析
  • 破除扫描边界Photoneo MotionCam-3D Color 解锁动态世界新维度
  • 京东疯狂投资具身智能:众擎机器人+千寻智能+逐际动力 | AI早报
  • 2021 RoboCom 世界机器人开发者大赛-本科组(复赛)解题报告 | 珂学家
  • [硬件电路-64]:模拟器件 -二极管在稳压电路中的应用
  • 物流链上的智慧觉醒:Deepoc具身智能如何重塑搬运机器人的“空间思维”
  • 库卡气体保护焊机器人省气的方法
  • Java IO流体系详解:字节流、字符流与NIO/BIO对比及文件拷贝实践
  • 大模型高效适配:软提示调优 Prompt Tuning
  • 【Windows】多标签显示文件夹