Tortoise-ORM与FastAPI集成:异步模型定义与实践
title: Tortoise-ORM与FastAPI集成:异步模型定义与实践
date: 2025/04/20 11:38:23
updated: 2025/04/20 11:38:23
author: cmdragon
excerpt:
Tortoise-ORM通过类继承方式定义数据模型,每个模型类对应数据库中的一张表。模型字段类型与数据库类型自动映射,支持主键、唯一约束、索引等配置。模型间通过外键建立关联,支持异步查询和CRUD操作。FastAPI集成时,通过register_tortoise初始化数据库连接,并结合Pydantic模型实现数据验证。常见错误包括字段验证失败和数据库连接超时,可通过中间件和连接池配置解决。
categories:
- 后端开发
- FastAPI
tags:
- Tortoise-ORM
- FastAPI
- 异步数据库
- 模型定义
- 数据库配置
- CRUD接口
- 错误处理

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
第一章 Tortoise-ORM异步模型定义基础
1.1 模型类创建方法
在FastAPI项目中,数据模型是连接业务逻辑与数据库的核心枢纽。Tortoise-ORM采用类继承方式定义模型,每个模型类对应数据库中的一张表。以下是用户模型的完整示例:
from tortoise.models import Model
from tortoise import fields
class User(Model):
id = fields.IntField(pk=True) # 主键字段,自动递增
username = fields.CharField(max_length=50, unique=True) # 唯一用户名
email = fields.CharField(max_length=100, index=True) # 带索引的邮箱字段
created_at = fields.DatetimeField(auto_now_add=True) # 自动记录创建时间
is_active = fields.BooleanField(default=True) # 账户激活状态
credit = fields.DecimalField(max_digits=10, decimal_places=2, default=0.0) # 精确数值存储
class Meta:
table = "auth_users" # 自定义表名
ordering = ["-created_at"] # 默认排序规则
该模型在数据库中会生成如下结构的表(以PostgreSQL为例):
CREATE TABLE auth_users
(
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP NOT NULL,
is_active BOOLEAN NOT NULL,
credit NUMERIC(10, 2) NOT NULL
);
1.2 字段类型映射原理
Tortoise-ORM的字段系统实现了Python类型与数据库类型的智能转换。当我们执行数据库迁移时,ORM会自动根据模型字段类型生成对应的DDL语句:
| Python字段类型 | PostgreSQL类型 | MySQL类型 | SQLite类型 |
|---|---|---|---|
| CharField | VARCHAR | VARCHAR | TEXT |
| UUIDField | UUID | CHAR(36) | TEXT |
| DatetimeField | TIMESTAMP | DATETIME(6) | TEXT |
| JSONField | JSONB | JSON | TEXT |
| FloatField | DOUBLE PRECISION | DOUBLE | REAL |
特殊的字段参数:
auto_now_add=True:仅在对象创建时记录时间auto_now=True:每次保存对象时更新时间description='字段说明':生成数据库注释db_index=True:创建独立索引(比index参数更灵活)
1.3 模型关联配置
关联关系配置是ORM的核心功能之一。我们通过外键字段建立模型间的关联:
class Author(Model):
name = fields.CharField(max_length=100)
class Book(Model):
title = fields.CharField(max_length=200)
author = fields.ForeignKeyField(
'models.Author',
related_name='books',
on_delete=fields.CASCADE
)
published_date = fields.DateField()
关联查询示例:
# 获取作者及其所有书籍
author = await Author.filter(name="J.K. Rowling").prefetch_related('books')
# 创建关联对象
await Book.create(
title="Harry Potter and the Philosopher's Stone",
author=author,
published_date=date(1997, 6, 26)
)
第二章 FastAPI集成实践
2.1 数据库配置
在FastAPI启动配置中初始化数据库连接:
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
app = FastAPI()
DB_CONFIG = {
"connections": {
"default": "postgres://user:password@localhost:5432/mydb"
},
"apps": {
"models": {
"models": ["models"],
"default_connection": "default",
}
},
"use_tz": True, # 启用时区支持
"timezone": "Asia/Shanghai"
}
register_tortoise(
app,
config=DB_CONFIG,
generate_schemas=True, # 自动生成表结构
add_exception_handlers=True # 启用ORM异常处理
)
2.2 路由与模型结合
创建完整的CRUD接口示例:
from pydantic import BaseModel
from fastapi import APIRouter
router = APIRouter()
class UserCreate(BaseModel):
username: str
email: str
@router.post("/users")
async def create_user(user: UserCreate):
db_user = await User.create(**user.dict())
return {
"id": db_user.id,
"created_at": db_user.created_at.isoformat()
}
@router.get("/users/{user_id}")
async def get_user(user_id: int):
user = await User.get_or_none(id=user_id).values(
"username", "email", "created_at")
return user or {"error": "User not found"}
第三章 课后Quiz
问题1:如何设置UUID主键?
A) id = fields.UUIDField()
B) id = fields.UUIDField(pk=True)
C) id = fields.UUIDField(primary_key=True)
正确答案:C
解析:在Tortoise-ORM中,设置主键需要显式指定primary_key参数。虽然pk是常用的快捷参数,但UUIDField必须使用完整的primary_key=True才能正确生成主键约束。
问题2:异步查询的优势包括?
A) 减少内存占用
B) 避免阻塞事件循环
C) 提高CPU利用率
正确答案:B
解析:异步查询允许事件循环在等待数据库响应时处理其他任务,特别适合高并发的I/O密集型场景。内存占用和CPU利用率主要与程序实现方式相关,并非异步的直接优势。
第四章 常见报错解决方案
4.1 字段验证失败(422错误)
错误示例:
{
"detail": [
{
"loc": [
"body",
"username"
],
"msg": "ensure this value has at most 50 characters",
"type": "value_error.any_str.max_length"
}
]
}
解决方法:
- 检查请求数据是否符合模型约束
- 在Pydantic模型中设置相同的验证规则
- 使用中间件捕获验证异常:
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=400,
content={"detail": exc.errors()},
)
4.2 数据库连接超时
错误信息:
DBConnectionError: Can't connect to MySQL server on 'localhost'
排查步骤:
- 验证数据库服务是否正常运行
- 检查连接字符串格式:
dialect://user:password@host:port/dbname - 增加连接池配置:
DB_CONFIG = {
"connections": {
"default": {
"engine": "tortoise.backends.asyncpg",
"credentials": {
"host": "localhost",
"port": "5432",
"database": "mydb",
"user": "user",
"password": "password",
"minsize": 3, # 最小连接数
"maxsize": 20 # 最大连接数
}
}
}
}
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:
Tortoise-ORM与FastAPI集成:异步模型定义与实践 | cmdragon's Blog
往期文章归档:
- 异步编程与Tortoise-ORM框架 | cmdragon's Blog
- FastAPI数据库集成与事务管理 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成与CRUD操作 | cmdragon's Blog
- FastAPI与SQLAlchemy同步数据库集成 | cmdragon's Blog
- SQLAlchemy 核心概念与同步引擎配置详解 | cmdragon's Blog
- FastAPI依赖注入性能优化策略 | cmdragon's Blog
- FastAPI安全认证中的依赖组合 | cmdragon's Blog
- FastAPI依赖注入系统及调试技巧 | cmdragon's Blog
- FastAPI依赖覆盖与测试环境模拟 | cmdragon's Blog
- FastAPI中的依赖注入与数据库事务管理 | cmdragon's Blog
- FastAPI依赖注入实践:工厂模式与实例复用的优化策略 | cmdragon's Blog
- FastAPI依赖注入:链式调用与多级参数传递 | cmdragon's Blog
- FastAPI依赖注入:从基础概念到应用 | cmdragon's Blog
- FastAPI中实现动态条件必填字段的实践 | cmdragon's Blog
- FastAPI中Pydantic异步分布式唯一性校验 | cmdragon's Blog
- 掌握FastAPI与Pydantic的跨字段验证技巧 | cmdragon's Blog
- FastAPI中的Pydantic密码验证机制与实现 | cmdragon's Blog
- 深入掌握FastAPI与OpenAPI规范的高级适配技巧 | cmdragon's Blog
- Pydantic字段元数据指南:从基础到企业级文档增强 | cmdragon's Blog
- Pydantic Schema生成指南:自定义JSON Schema | cmdragon's Blog
- Pydantic递归模型深度校验36计:从无限嵌套到亿级数据的优化法则 | cmdragon's Blog
- Pydantic异步校验器深:构建高并发验证系统 | cmdragon's Blog
- Pydantic根校验器:构建跨字段验证系统 | cmdragon's Blog
- Pydantic配置继承抽象基类模式 | cmdragon's Blog
- Pydantic多态模型:用鉴别器构建类型安全的API接口 | cmdragon's Blog
- FastAPI性能优化指南:参数解析与惰性加载 | cmdragon's Blog
- FastAPI依赖注入:参数共享与逻辑复用 | cmdragon's Blog
- FastAPI安全防护指南:构建坚不可摧的参数处理体系 | cmdragon's Blog
- FastAPI复杂查询终极指南:告别if-else的现代化过滤架构 | cmdragon's Blog
- FastAPI 核心机制:分页参数的实现与最佳实践 | cmdragon's Blog
- FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 ️ | cmdragon's Blog
- FastAPI 自定义参数验证器完全指南:从基础到高级实战 | cmdragon's Blog
- FastAPI 参数别名与自动文档生成完全指南:从基础到高级实战 | cmdragon's Blog
Tortoise-ORM与FastAPI集成:异步模型定义与实践的更多相关文章
- JavaScript 学习笔记之线程异步模型
核心的javascript程序语言并没有包含任何的线程机制,客户端javascript程序也没有任何关于线程的定义,事件驱动模式下的javascript语言并不能实现同时执行,即不能同时执行两个及以上 ...
- beego——模型定义
复杂的模型定义不是必须的,此功能用作数据库数据转换和自动建表 默认的表名规则,使用驼峰转蛇形: AuthUser -> auth_user Auth_User -> auth__user ...
- Task C# 多线程和异步模型 TPL模型 【C#】43. TPL基础——Task初步 22 C# 第十八章 TPL 并行编程 TPL 和传统 .NET 异步编程一 Task.Delay() 和 Thread.Sleep() 区别
Task C# 多线程和异步模型 TPL模型 Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task ...
- 结合异步模型,再次总结Netty多线程编码最佳实践
更多技术分享可关注我 前言 本文重点总结Netty多线程的一些编码最佳实践和注意事项,并且顺便对Netty的线程调度模型,和异步模型做了一个汇总.原文:结合异步模型,再次总结Netty多线程编码最 ...
- 【重磅】iNeuOS工业互联平台,系统集成业务模型和WEB组态视图建模集成3D模型
目 录 1. 概述... 1 2. 平台演示... 2 3. 系统集成业务模型... 2 4. WEB组态视图建模集成3D模型... 3 5. ...
- 以两种异步模型应用案例,深度解析Future接口
摘要:本文以实际案例的形式分析了两种异步模型,并从源码角度深度解析Future接口和FutureTask类. 本文分享自华为云社区<[精通高并发系列]两种异步模型与深度解析Future接口(一) ...
- 【高并发】两种异步模型与深度解析Future接口
大家好,我是冰河~~ 本文有点长,但是满满的干货,以实际案例的形式分析了两种异步模型,并从源码角度深度解析Future接口和FutureTask类,希望大家踏下心来,打开你的IDE,跟着文章看源码,相 ...
- .NET - 基于事件的异步模型
注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...
- Entity Framework 6 Recipes 2nd Edition(11-1)译 -> 从“模型定义”函数返回一个标量值
第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking ...
- Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 用”模型定义”函数过滤实体集
11-2. 用”模型定义”函数过滤实体集 问题 想要创建一个”模型定义”函数来过滤一个实体集 解决方案 假设我们已有一个客户(Customer)和票据Invoice)模型,如Figure 11-2所示 ...
随机推荐
- Linux中如何将txt文件转为png格式
Linux中如何将txt文件转为png格式 linux将txt文件转为png格式如果文本中没有中文,使用enscript,如果文本包含中文,使用paps命令.但是实际使用中,paps部分版本也不支持中 ...
- Project Euler 307 题解
主要是规避误差.即求 \[\frac{k^n}{n^k} \] 微分一下得到递推式.然后根据斯特林近似(byd 这里还需要 \(1\) 后的第一项..) ...
- 大数据之路Week10_day04 (Hbase的二级索引,二级索引的本质就是建立各列值与行键之间的映射关系)
二级索引的本质就是建立各列值与行键之间的映射关系 HBASE是在hadoop之上构建非关系型,面向列存储的开源分布式结构化数据存储系统. Hbase的局限性: HBase本身只提供基于行键和全表扫描的 ...
- ARC101E题解
前言 此片题解大致按照笔者做题思路进行讲解. 简要题意 有一棵树,树上有偶数个节点.你需要给这些点两两配对,一组已经配对的点会将两点之间的树边进行一次覆盖.一组合法方案需要满足树上所有边都被覆盖至少一 ...
- ABC391D题解
前置知识: map priority_queue 思路 考虑预处理每一个图块在第几秒后会被删除. 如何预处理?我使用了一种非常暴力的做法,首先处理的过程肯定是从下往上的,于是每一个图块能被删除一定是它 ...
- thinkphp6实现仿微信朋友圈,用户可发布图片和文字内容,用户可评论,其他用户可评论文章,也可回复用户评论,多层级评论,无限级评论
功能:仿微信朋友圈,用户可发布图片和文字内容,用户可评论,其他用户可评论文章,也可回复用户评论,多层级评论,无限级评论数据库示例:朋友圈内容表 article表:id content image li ...
- .NET周刊【2月第4期 2025-02-23】
国内文章 [翻译] 为什么 Tracebit 用 C# 开发 https://www.cnblogs.com/liuliu-66/p/-/why-tracebit-is-written-in-c-sh ...
- Win系统重装备忘
蒙德,致态的盘坏块激增,似乎损坏到了系统文件:屏幕截屏会卡,关机后直接该块硬盘内的文件内容回滚,出现驱动报错要求重启... 然后尝试了DiskGenuis迁移系统,PE模式不能用,热迁移后似乎正常分区 ...
- 多机器的键鼠互通——Synergy/Deskflow配置记录
Synergy (1.14.6) 情况一样,那么感觉就是机器之间TCP连接有问题,测试不同 一些测试命令 ss -tlnp | grep 24800 # 查看端口情况 sudo lsof -i :24 ...
- js回忆录(3) -- 循环语句,前后缀运算符
计算机对于大批量数据的处理速度比起人类不知道快了多少,因此对于重复的操作,使用循环语句处理是很方便的,对于我们前端来说,给同一标签的元素绑定事件啦,tab切换啦,左右联动效果啦,等等都可以使用循环语句 ...