当前位置: 首页 > 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.dtcms.com/a/291172.html

相关文章:

  • GraphRAG快速入门和原理理解
  • 在线教育如何设置视频问答/视频弹题?——重塑在线教育的互动体验
  • 元宇宙工厂漫游指南:VR可视化在设备巡检与远程运维中的沉浸式应用
  • Component cannot be used as a JSX component
  • 网络数据编码技术及其应用场景的全面解析
  • 基于Vue与CloudBase AI Toolkit的色觉识别Web应用开发报告:VibeCoding新范式实践
  • 基于dcmtk的dicom工具 第八章 echoSCU-dicom测试连接
  • 广东餐饮服务中级水平测试精选题库
  • 基于Python的多传感器融合的障碍物检测与避障演示
  • WPF 项目设置应用程序图标和设置程序集图标
  • 搭建种草商城框架指南
  • 修复WSL安装失败(错误: 0x80248014 )并安装K8S
  • 低空经济展 | 约克科技携小型化测试设备亮相2025深圳eVTOL展
  • Linux物理地址空间入门:从硬件到内核内存的基石
  • Javascript--事件
  • 耐达讯RS232转Ethercat网关:建筑驱动连接的“秘密武器”
  • 【系统全面】Socket编程——基础知识介绍
  • 2x2矩阵教程
  • AI赋能中医传承:智慧医疗新时代解决方案
  • 如何避免redis分布式锁失效
  • 搭建前端页面,介绍对应标签
  • 前端之学习后端java小白(一)之SDKMAN
  • Typecho目录树插件开发:从后端解析到前端渲染全流程
  • AI革命带来的便利
  • [特殊字符] Java反射从入门到飞升:手撕类结构,动态解析一切![特殊字符]
  • 多线程--线程池
  • 【docker】分享一个好用的docker镜像国内站点
  • dev tools的使用
  • FastMCP全篇教程以及解决400 Bad Request和session termination的问题
  • 理解向量及其运算-AI云计算数值分析和代码验证