Tortoise ORM 入门指南:Python 异步优先的 ORM
Tortoise ORM 是 asyncio 原生、Django 风格的 Python ORM:模型定义、异步 CRUD、关系映射与查询 API。高并发 Web 应用的现代化数据库之选。
直接回答:Tortoise ORM 是异步优先的 Python ORM:主要数据库 I/O 通过可等待接口完成,可在等待期间让出事件循环;API 设计致敬 Django ORM(filter()、get()、create()),学习曲线平缓——FastAPI/Sanic 等异步框架的数据库好搭档。
为什么是异步 ORM
异步框架里用同步 ORM,若直接在事件循环线程执行阻塞查询,会影响同进程其他协程;将同步访问放到受控线程池是另一种方案,并非只能更换 ORM。Tortoise 让所有操作都是 awaitable:等待数据库响应时,事件循环照常服务其他请求。
安装与初始化
pip install "tortoise-orm>=1,<2"
下面将模型保存在可导入的 models.py;CRUD 与关系查询是异步函数体片段,需在初始化完成后运行,独立脚本退出前调用 await Tortoise.close_connections()。
from tortoise import Tortoise, fields
from tortoise.models import Model
class Team(Model):
id = fields.IntField(primary_key=True)
name = fields.CharField(max_length=100)
class Event(Model):
id = fields.IntField(primary_key=True)
name = fields.CharField(max_length=200)
team = fields.ForeignKeyField("models.Team", related_name="events")
async def init():
await Tortoise.init(db_url="sqlite://events.db", modules={"models": ["models"]})
await Tortoise.generate_schemas() # 仅演示初始化;生产使用迁移
异步 CRUD
# 增
team = await Team.create(name="火箭队")
# 查
team = await Team.get(name="火箭队")
teams = await Team.filter(name__contains="火").order_by("-id").limit(10)
exists = await Team.exists(name="火箭队")
# 改
team.name = "休斯敦火箭"
await team.save()
await Team.filter(id=team.id).update(name="火箭") # 批量
# 删
await team.delete()
await Team.filter(name="测试").delete() # 批量
Django 用户倍感亲切:filter、get、__contains 双下划线查找——心智模型直接平移。
关系查询
# 预取关联(避免 N+1)
teams = await Team.all().prefetch_related("events")
for t in teams:
print(t.name, len(t.events))
# 反查
events = await Event.filter(team__name="火箭队")
prefetch_related / select_related 的概念与 Django 一致。
FastAPI 集成
官方注册器接管生命周期:
from fastapi import FastAPI
from models import Team
from tortoise.contrib.fastapi import register_tortoise
app = FastAPI()
register_tortoise(
app,
db_url="sqlite://events.db",
modules={"models": ["models"]},
generate_schemas=True, # 仅开发演示,生产改 False 并先执行迁移
)
@app.get("/teams")
async def list_teams():
return await Team.all().limit(100).values("id", "name")
路由函数里直接 await ORM 调用——没有会话传递、没有依赖注入样板,异步路径干净彻底。
生产要点
- 迁移:Tortoise 1.x 官方推荐内置迁移:配置 migrations 包后使用
tortoise init、tortoise makemigrations、tortoise migrate;Aerich 是旧项目的历史替代路径,升级需遵循迁移指南; - 连接池:按所用后端的连接配置调整,例如 asyncpg 的 minsize/maxsize,不能把同一组选项直接用于 SQLite 或其他驱动;
- 事务:
async with in_transaction()保证多步写一致性。
常见问题(FAQ)
Q:Tortoise 和 SQLAlchemy 2.0 异步怎么选?
A:Tortoise 简单直接(Django 式 API);SQLAlchemy 功能更深(复杂查询、Core 层、生态厚)。快速开发 Tortoise,复杂系统 SQLAlchemy。
Q:能在 Django 里用 Tortoise 吗?
A:技术上可以集成,但需独立管理连接生命周期、模型与迁移,不能直接替换 Django Admin、认证等对原生 ORM 的依赖。通常优先使用 Django 自带 ORM。
Q:同步脚本能用吗?
A:可以但要包 asyncio.run()。纯同步项目没必要用它——Peewee/SQLAlchemy 更合适。
官方参考
本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。