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 更合适。

官方参考

本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台