惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
Y
Y Combinator Blog
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
aimingoo的专栏
aimingoo的专栏
Jina AI
Jina AI
The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Check Point Blog
M
MIT News - Artificial intelligence
Last Week in AI
Last Week in AI
V
V2EX
腾讯CDC
F
Fortinet All Blogs
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss

博客园 - 一名程序媛呀

Anki插件开发必知必会:钩子函数与右键菜单定制 httpx 传参总报错?这次把 GET、POST、文件上传到响应处理的坑给你一次填平 从卡顿到丝滑:FastAPI 调用外部 API 的正确姿势(httpx 实战) 还在 XHR、Fetch 和 Axios 之间纠结?我踩过的坑,希望你一个都不用碰到 你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南 Uvicorn、Gunicorn 傻傻分不清?FastAPI 生产部署避坑指南 Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招! 刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API 别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了 掏出手机就能搭个 WebDAV 同步服务器?这操作有点香 别只盯着GitBook了!这个文档神器让你的笔记秒变网站 写爬虫时用了代理还被封?Python 代理的那些隐藏坑,我替你踩明白了 FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好 旧手机别扔!用 Termux 搭个私人云盘,比网盘香多了 你的FastAPI又在服务器上“跑不起来”了?来,今天咱把打包这件事彻底聊透 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 前端包管理咋选?我从npm叛逃到pnpm的血泪史(附避坑指南) 聊聊 fetch 使用中我踩过的那些坑和正确打开方式 FastApiAdmin 后端接口开发好了,前端管理界面怎么调用与显示? 给 FastApiAdmin 加个“会议纪要”模块,我把后端二次开发的坑踩了个遍 我用了FastApiAdmin后,连夜把踩过的坑都整理出来了 告别 Typora 后的新欢:我把所有笔记迁移到了 Obsidian 这个“第二大脑” 你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线 让 FastAPI Agent 思考不阻塞:手把手教你实现异步任务与后台处理方案 让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践 FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“ 初探:用 FastAPI 搭建你的第一个 AI Agent 接口 FastAPI 少有人提的实用技巧:把 Depends 依赖提到路由层,代码少写60% FastAPI 生产环境静态文件完全指南:从 /favicon.ico 404 到 HSTS 混合内容,一次全根治 用了loguru我才明白,Python日志还能这么写
FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了
一名程序媛呀 · 2026-04-17 · via 博客园 - 一名程序媛呀

是不是每次开新项目,到了选ORM这一步,心里的两个小人就开始打架? 一个说:“用 SQLAlchemy 吧,生态稳如老狗,万一出问题网上随便一搜就有答案。” 另一个立马反驳:“异步时代了老铁,用 Tortoise-ORM 它不香吗?那代码写起来多轻快。” 旁边还有个声音幽幽飘来:“要不试试官方亲儿子 SQLModel ?”

别笑,这就是我之前的真实写照。我在 GitHub 上光是看这三个库的对比 issue 就刷了一下午,咖啡喝了三杯,一行代码没写。 最后索性一不做二不休,把这三个家伙挨个拉出来遛遛,写了个简单的用户CRUD,这才算心里有了谱。今天就把这份热乎的经验总结分享给你,主打一个听人劝吃饱饭。


🎯 这三兄弟到底谁是谁?

好,咱们先来盘盘这三位的底细。别嫌啰嗦,搞清楚它们的定位,你心里的秤杆子才能放平。

- SQLAlchemy 2.0:稳重的老大哥

这家伙在 Python 圈子的地位,好比 NBA 里的詹姆斯,资历老、技术全面、粉丝基础庞大。
以前总被人吐槽异步不行,但现在 2.0 版本原生支持 async/await,直接把最后一块短板也给补上了。

缺点就是学习曲线陡了点,配置起来稍微有点啰嗦。

- Tortoise-ORM:轻巧的赛车手

它就是为异步而生的,灵感来自 Django ORM。如果你从 Django 转过来,看这代码简直亲切得想哭。

它跑得快,占用资源少,但生态和社区肯定没老大哥那么广,有时候遇到冷门坑得自己去翻源码。

- SQLModel:官方的亲儿子

它是 FastAPI 作者 tiangolo 搞出来的,最大的杀招就是把 Pydantic 的 Schema 和 SQLAlchemy 的 Model 合二为一了。你再也不用写两份几乎一模一样的类了! 这简直是治愈强迫症的良药。

但它比较新,底层其实跑的还是 SQLAlchemy,可以理解为给老大哥穿了一身更潮的衣服。


🛠️ 别光说不练,上代码看看谁更顺手

咱们看个最简单的“创建用户”功能,直观感受下代码量的差距和手感。

1. SQLAlchemy 2.0 (异步版)

# 定义模型 (models.py)
class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(String(100), unique=True)

# Pydantic 校验 (schemas.py)
class UserCreate(BaseModel):
    email: str

# 路由逻辑 (main.py)
async def create_user(user_data: UserCreate, session: AsyncSession):
    new_user = User(**user_data.model_dump())
    session.add(new_user)
    await session.commit()
    await session.refresh(new_user)
    return new_user

⚠️ 经验之谈:看到没,模型和校验类是分开的。这里千万别学我当初偷懒,直接用同一个类又当校验又当数据库模型, 后面业务一复杂,比如数据库里要存个不对外暴露的字段,那改起来就是牵一发动全身。

2. Tortoise-ORM

# 定义模型 (models.py) 
class User(Model):
    id = fields.IntField(pk=True)
    email = fields.CharField(max_length=100, unique=True)

    class Meta:
        table = "users"

# 定义 Pydantic Schema (schemas.py)
class UserCreate(BaseModel):
    email: str

# 路由逻辑 (main.py)
async def create_user(user_data: UserCreate):
    new_user = await User.create(**user_data.model_dump())
    return new_user

是不是清爽多了?直接 User.create() 一把梭。但这也是它容易翻车的地方,因为太像 Django 了,有些人会忘记它底层的异步特性, 在循环里直接 await 搞出一堆慢查询。

3. SQLModel

# 定义模型 + Schema 合体 (models.py)
class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    email: str = Field(max_length=100, unique=True)

# 路由逻辑 (main.py)
async def create_user(user_data: User, session: AsyncSession):
    session.add(user_data)
    await session.commit()
    await session.refresh(user_data)
    return user_data

你可能会问:“这不就写了一个类吗?那登录时的密码字段怎么处理?” 问得好!SQLModel 的做法是用继承,再写个 UserCreate(User) 把敏感字段过滤掉。虽然文件少了,但对继承逻辑的理解要求高了点,刚上手容易蒙圈。


🤔 最后啰嗦一句,到底怎么选?

其实这个问题的答案,就像买螺丝刀,没有最贵的,只有最合适的。

🔹 如果你是团队开发大型项目:

别犹豫,直接上 SQLAlchemy 2.0。 生态和稳定性压倒一切,你踩过的坑前人早就把路填平了。虽然代码多点,但可控性强。

🔹 如果你是自己搞个小玩具,或者想快速出活:

Tortoise-ORM 会让你爽到飞起。 代码少,逻辑直观,异步性能杠杠的。

🔹 如果你是个强迫症,或者重度 Pydantic 爱好者:

试试 SQLModel 吧,官方亲儿子的名头不是白给的。 统一模型的感觉真的非常治愈。不过要做好当小白鼠的心理准备,毕竟它现在还是 0.x 版本。

说来说去,工具只是手段,能帮你解决问题的就是好工具。这篇文章也只是我个人的一点主观感受,真正哪个适合你,还得自己动手试试才知道。


好啦,今天先唠这么多。如果你觉得这篇用实战肝出来的对比有点用,别藏私,点个赞+关注,或者直接转发给你那个正在纠结 FastAPI 怎么写的同事。

技术路漫漫,咱们搭伴走不孤单。下次再遇到什么奇葩 Bug,咱们接着聊!👋