Tortoise ORM 全面指南:从基础到高级应用
目录
简介
Tortoise ORM 是一个强大的异步 Python ORM,专为现代异步 Web 框架设计。它结合了 Django ORM 的直观性和异步编程的高效性,为开发者提供了一个理想的数据库交互解决方案。
主要特性
- 完全异步操作
- 类似 Django 的 API
- 强类型支持
- 复杂关系处理
- 丰富的查询 API
- 事务支持
- 多数据库支持(SQLite, PostgreSQL, MySQL)
安装与配置
基本安装
pip install tortoise-orm
数据库特定安装
pip install tortoise-orm[asyncpg] # PostgreSQL
pip install tortoise-orm[aiomysql] # MySQL
基本配置
from tortoise import Tortoise, run_async
async def init():
await Tortoise.init(
db_url='sqlite://db.sqlite3',
modules={'models': ['myapp.models']}
)
await Tortoise.generate_schemas()
run_async(init())
基本用法
模型定义
from tortoise import Model, fields
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=50, unique=True)
email = fields.CharField(max_length=100, unique=True)
password = fields.CharField(max_length=128)
is_active = fields.BooleanField(default=True)
created_at = fields.DatetimeField(auto_now_add=True)
def __str__(self):
return self.username
class Post(Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=200)
content = fields.TextField()
author = fields.ForeignKeyField('models.User', related_name='posts')
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
def __str__(self):
return self.title
CRUD 操作
# 创建
user = await User.create(username='johndoe', email='john@example.com', password='securepass')
# 读取
user = await User.get(username='johndoe')
all_users = await User.all()
# 更新
await User.filter(id=1).update(is_active=False)
# 删除
await User.filter(id=1).delete()
高级特性
复杂查询
from tortoise.expressions import Q
# 组合查询
active_users = await User.filter(
Q(is_active=True) & (Q(username__contains='john') | Q(email__contains='john'))
)
# 排除
non_admin_users = await User.exclude(username='admin')
# 排序
sorted_users = await User.all().order_by('-created_at', 'username')
# 限制结果
recent_users = await User.all().order_by('-created_at').limit(5)
关系查询
# 预加载关联对象
users_with_posts = await User.all().prefetch_related('posts')
# 反向关系查询
user = await User.get(id=1)
user_posts = await user.posts.all()
# 多对多关系
class Tag(Model):
name = fields.CharField(max_length=50)
posts = fields.ManyToManyField('models.Post', related_name='tags')
# 添加多对多关系
post = await Post.get(id=1)
tag = await Tag.get(id=1)
await post.tags.add(tag)
# 查询多对多关系
posts_with_tag = await Post.filter(tags__id=1)
聚合和注解
from tortoise.functions import Count, Avg, Sum
# 计算每个用户的帖子数
users_post_count = await User.annotate(post_count=Count('posts'))
# 获取帖子数量最多的用户
most_active_user = await User.annotate(post_count=Count('posts')).order_by('-post_count').first()
# 计算平均帖子长度
avg_post_length = await Post.annotate(avg_length=Avg('content__length')).values('avg_length')
原生 SQL
# 执行原生 SQL 查询
users = await User.raw("SELECT * FROM user WHERE is_active = 1")
# 执行原生 SQL 命令
await Tortoise.get_connection('default').execute_query("UPDATE user SET is_active = 1 WHERE id = 1")
性能优化
批量操作
# 批量创建
users_data = [
{"username": f"user{i}", "email": f"user{i}@example.com"}
for i in range(100)
]
await User.bulk_create([User(**data) for data in users_data])
# 批量更新
await User.filter(is_active=False).update(is_active=True)
索引优化
class OptimizedPost(Model):
title = fields.CharField(max_length=200, index=True)
content = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True, index=True)
class Meta:
indexes = [("title", "created_at")]
连接池配置
await Tortoise.init(
db_url='postgres://user:pass@localhost:5432/dbname',
modules={'models': ['myapp.models']},
connections={
'default': {
'engine': 'tortoise.backends.asyncpg',
'credentials': {
'host': 'localhost',
'port': '5432',
'user': 'user',
'password': 'pass',
'database': 'dbname',
'minsize': 1,
'maxsize': 10,
}
}
}
)
测试策略
使用测试数据库
from tortoise.contrib.test import initializer, finalizer
def setUpModule():
initializer(['myapp.models'], db_url='sqlite://:memory:')
def tearDownModule():
finalizer()
class TestUser(TestCase):
async def test_create_user(self):
user = await User.create(username='testuser', email='test@example.com')
self.assertEqual(await User.all().count(), 1)
self.assertEqual(user.username, 'testuser')
事务测试
from tortoise.transactions import in_transaction
async def test_transaction():
async with in_transaction():
user = await User.create(username='transactionuser', email='trans@example.com')
# 事务会在这里回滚,不会实际创建用户
assert await User.filter(username='transactionuser').exists() == False
与其他库的集成
与 FastAPI 集成
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
app = FastAPI()
register_tortoise(
app,
db_url="sqlite://db.sqlite3",
modules={"models": ["myapp.models"]},
generate_schemas=True,
add_exception_handlers=True,
)
@app.get("/users")
async def get_users():
return await User.all()
与 Pydantic 集成
from tortoise.contrib.pydantic import pydantic_model_creator
UserPydantic = pydantic_model_creator(User)
@app.post("/users")
async def create_user(user: UserPydantic):
user_obj = await User.create(**user.dict(exclude_unset=True))
return await UserPydantic.from_tortoise_orm(user_obj)
最佳实践
-
使用异步上下文管理器:在处理长时间运行的操作时,使用异步上下文管理器来确保资源被正确释放。
-
合理使用预加载:使用
prefetch_related
来减少数据库查询次数,但要避免过度预加载。 -
批量操作:对于大量数据的操作,使用批量创建、更新或删除方法。
-
使用事务:对于需要保证一致性的复杂操作,使用事务来确保原子性。
-
索引优化:根据查询模式合理设置索引,但要避免过度索引。
-
异步迭代:处理大量数据时,使用异步迭代器来减少内存使用。
async for user in User.all():
# 处理每个用户
- 定期清理连接池:在长时间运行的应用中,定期重置数据库连接池以防止连接泄漏。
常见问题及解决方案
-
循环导入问题:
解决方案:使用字符串模型引用或延迟导入。 -
大量数据的内存问题:
解决方案:使用limit
和offset
进行分页查询,或使用异步迭代器。 -
复杂查询性能问题:
解决方案:使用select_related
和prefetch_related
优化查询,必要时使用原生 SQL。 -
多数据库支持:
解决方案:使用 Tortoise 的多数据库配置功能,为不同模型指定不同的数据库。
实际应用场景
-
博客系统:
使用 User、Post、Comment 和 Tag 模型,展示复杂的关系查询和内容管理。 -
电子商务平台:
实现 Product、Order、Customer 模型,展示事务处理和库存管理。 -
社交媒体应用:
使用 User、Post、Like、Follow 模型,展示高并发场景下的性能优化。 -
内容管理系统 (CMS):
实现灵活的内容类型和字段定义,展示动态模型创建和管理。
与其他 ORM 的比较
-
vs SQLAlchemy:
- Tortoise ORM 专注于异步,API 设计更简洁。
- SQLAlchemy 功能更全面,生态系统更大。
-
vs Django ORM:
- Tortoise ORM 支持异步操作,更适合现代异步框架。
- Django ORM 与 Django 框架深度集成,提供更多开箱即用的功能。
-
vs Peewee:
- Tortoise ORM 原生支持异步操作。
- Peewee 更轻量,但主要用于同步操作。
结语
Tortoise ORM 为 Python 异步编程提供了一个强大而灵活的 ORM 解决方案。它结合了直观的 API 设计和高效的异步操作,使得在现代 Web 应用中处理数据库操作变得简单而高效。无论是构建小型项目还是大型应用,Tortoise ORM 都能提供必要的工具和灵活性。
随着异步编程在 Python 社区中的日益普及,Tortoise ORM 的重要性可能会进一步提升。持续关注其发展和最佳实践,将有助于构建更高效、更可扩展的 Python 应用。