FastAPI与Tortoise-ORM开发的神奇之旅
title: FastAPI与Tortoise-ORM开发的神奇之旅
date: 2025/05/05 00:15:48
updated: 2025/05/05 00:15:48
author: cmdragon
excerpt:
FastAPI与Tortoise-ORM结合实现全链路开发,涵盖环境配置、数据模型定义、Pydantic模式设计及API端点实现。文章模型包含软删除功能,通过is_deleted
字段实现逻辑删除。API支持创建、分页查询、条件更新和软删除操作,确保数据安全与完整性。分页机制通过offset
和limit
实现,条件更新使用exclude_unset=True
避免未传字段被覆盖。软删除通过filter().update()
实现原子操作。系统具备用户认证、输入验证、防注入和细粒度权限控制等安全特性。
categories:
- 后端开发
- FastAPI
tags:
- FastAPI
- TortoiseORM
- 全链路开发
- 数据模型
- API端点
- 分页机制
- 软删除


扫描二维码
关注或者微信搜一搜:编程智域 前端至全栈交流与成长
探索数千个预构建的 AI 应用,开启你的下一个伟大创意:https://tools.cmdragon.cn/
从API到数据库:FastAPI + Tortoise-ORM全链路开发指南
1. 环境准备与包安装
首先创建Python虚拟环境并安装必要依赖:
python -m venv venv
source venc/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
pip install fastapi uvicorn tortoise-orm pydantic python-multipart
2. 数据模型定义
创建包含软删除功能的文章模型:
# models.py
from tortoise.models import Model
from tortoise import fields
class Article(Model):
id = fields.IntField(pk=True)
title = fields.CharField(max_length=255)
content = fields.TextField()
author_id = fields.IntField()
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
is_deleted = fields.BooleanField(default=False)
class Meta:
table = "articles"
class PydanticMeta:
exclude = ["is_deleted"]
3. Pydantic模式定义
定义请求响应数据结构:
# schemas.py
from pydantic import BaseModel
from datetime import datetime
class ArticleCreate(BaseModel):
title: str
content: str
class ArticleUpdate(BaseModel):
title: str | None = None
content: str | None = None
class ArticleResponse(BaseModel):
id: int
title: str
content: str
author_id: int
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True
4. FastAPI应用配置
配置数据库连接和路由:
# main.py
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from tortoise.contrib.fastapi import register_tortoise
app = FastAPI()
# 数据库配置
DATABASE_URL = "sqlite://./db.sqlite3"
register_tortoise(
app,
db_url=DATABASE_URL,
modules={"models": ["models"]},
generate_schemas=True,
add_exception_handlers=True,
)
# 模拟用户认证
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
return {"id": 1} # 模拟返回用户信息
5. 完整API端点实现
5.1 创建文章
@app.post("/articles", response_model=ArticleResponse)
async def create_article(
article: ArticleCreate,
user: dict = Depends(get_current_user)
):
db_article = await Article.create(
**article.dict(),
author_id=user["id"]
)
return await ArticleResponse.from_tortoise_orm(db_article)
5.2 分页查询
@app.get("/articles", response_model=list[ArticleResponse])
async def list_articles(
page: int = 1,
per_page: int = 10
):
skip = (page - 1) * per_page
query = Article.all().offset(skip).limit(per_page)
return await ArticleResponse.from_queryset(query)
5.3 条件更新
@app.patch("/articles/{article_id}", response_model=ArticleResponse)
async def update_article(
article_id: int,
update_data: ArticleUpdate,
user: dict = Depends(get_current_user)
):
# 只允许作者修改自己的文章
db_article = await Article.get_or_none(id=article_id, author_id=user["id"])
if not db_article:
raise HTTPException(status_code=404, detail="Article not found")
await db_article.update_from_dict(update_data.dict(exclude_unset=True))
await db_article.save()
return await ArticleResponse.from_tortoise_orm(db_article)
5.4 软删除
@app.delete("/articles/{article_id}")
async def delete_article(
article_id: int,
user: dict = Depends(get_current_user)
):
updated_count = await Article.filter(
id=article_id,
author_id=user["id"]
).update(is_deleted=True)
if not updated_count:
raise HTTPException(status_code=404, detail="Article not found")
return {"message": "Article deleted"}
6. 关键实现解析
6.1 分页机制原理
- 计算skip值:
skip = (page - 1) * per_page
- 数据库查询使用offset和limit实现分页
- 实际生产环境建议使用游标分页(Cursor Pagination)
6.2 条件更新安全
- 通过
get_or_none
确保记录存在 - 使用
filter().update()
实现原子操作 exclude_unset=True
忽略未传字段
6.3 软删除实现
- 添加is_deleted字段
- 重写默认查询过滤器:
class SoftDeleteManager(fields.Model):
def get_queryset(self):
return super().get_queryset().filter(is_deleted=False)
7. 课后Quiz
Q1:如何防止SQL注入攻击?
A:使用ORM的参数化查询,避免拼接SQL语句。Tortoise-ORM会自动处理查询参数,例如:
await Article.filter(title="Safe' OR 1=1--")
实际生成的SQL会是参数化查询,特殊字符会被正确转义
Q2:为什么在更新时使用exclude_unset=True?
A:该参数会忽略未提供的字段,实现部分更新。例如用户只修改标题时,不会影响content字段
Q3:如何实现真正的物理删除?
A:直接使用delete()方法:
await Article.filter(id=1).delete()
8. 常见报错解决方案
错误1:422 Validation Error
- 原因:请求体不符合Pydantic模型要求
- 解决:检查请求头Content-Type是否正确(应为application/json),确认字段类型和必填项
错误2:404 Not Found
- 原因:尝试操作不存在的记录
- 解决:在更新/删除前先使用get_or_none检查记录是否存在
错误3:RuntimeError - Event loop closed
- 原因:在同步代码中调用异步方法
- 解决:确保所有数据库操作都在async函数中执行,使用await调用
启动服务命令:
uvicorn main:app --reload
访问 http://localhost:8000/docs 即可测试API接口。本文实现的系统具备以下安全特性:
- 用户认证隔离数据访问
- 所有输入参数自动验证
- 数据库操作防注入
- 细粒度的权限控制
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
,阅读完整的文章:FastAPI与Tortoise-ORM开发的神奇之旅 | cmdragon's Blog
往期文章归档:
- DDD分层设计与异步职责划分:让你的代码不再“异步”混乱 | cmdragon's Blog
- 异步数据库事务锁:电商库存扣减的防超卖秘籍 | cmdragon's Blog
- FastAPI中的复杂查询与原子更新指南 | cmdragon's Blog
- 深入解析Tortoise-ORM关系型字段与异步查询 | cmdragon's Blog
- FastAPI与Tortoise-ORM模型配置及aerich迁移工具 | cmdragon's Blog
- 异步IO与Tortoise-ORM的数据库 | cmdragon's Blog
- FastAPI数据库连接池配置与监控 | cmdragon's Blog
- 分布式事务在点赞功能中的实现 | cmdragon's Blog
- Tortoise-ORM级联查询与预加载性能优化 | cmdragon's Blog
- 使用Tortoise-ORM和FastAPI构建评论系统 | cmdragon's Blog
- 分层架构在博客评论功能中的应用与实现 | cmdragon's Blog
- 深入解析事务基础与原子操作原理 | cmdragon's Blog
- 掌握Tortoise-ORM高级异步查询技巧 | cmdragon's Blog
- FastAPI与Tortoise-ORM实现关系型数据库关联 | cmdragon's Blog
- 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
- XML Sitemap
FastAPI与Tortoise-ORM开发的神奇之旅的更多相关文章
- ORM开发之解析lambda实现完整查询(附测试例子)
上次讲解了怎么解析匿名对象(ORM开发之解析lambda实现group查询),这次来实现解析二元运算,完成基本条件语法 先看一个表达式 query.Where(b => b.Number == ...
- c++::Mysql::ORM 开发环境搭建
官网地址:https://www.codesynthesis.com/products/odb/ 环境搭建:ubuntu16.04-64 1.安装mysqlClient sudo apt-get in ...
- ORM开发之解析lambda实现group查询(附测试例子)
目的:以编程方式实现group查询,在开发ORM时,需要达到这样的效果 先看一个简单的group语句 select BarCode,ProductName,COUNT(BarCode) as tota ...
- ORM 开发环境之利器:MVC 中间件 FreeSql.AdminLTE
前言 这是一篇纯技术干货的分享文章,FreeSql 已经基本完成 .NETCore 最方便的 ORM 使命,我们正在筹备生态的建立,比如 ABP 中如何使用 FreeSql 的实现,需要各种各样的扩展 ...
- 使用 kbmmw 的ORM开发纯REST数据库访问服务
运行环境: WIN 10 X64 delphi 10.2.2 kbmmw 5.05.11 Firefox 58.0.2 今天使用最新的kbmmw 版本做一个基于ORM的纯数据库访问的REST 服务器 ...
- FastAPI:一个测试人员视角的教程
前言 教程肯定谈不上了,主要还是就自己的理解分享内容而已 内容是连官方文档的基础教程都没涵盖起的 建议直接看官方文档 以个人视角来分享,希望各位通过这个可以写接口了 需要自取 完整视频链接:https ...
- FastAPI小项目实战:电影列表(Vue3 + FastAPI)
假期过半, FastAPI + Vue3项目实战 视频也算录完了,尽管项目简单(2张表 共7个接口 4个页面) 起因 在6月底的时候开始录制了FastAPI官方文档中的新手教程部分(实际还没有官网文档 ...
- 自己开发轻量级ORM(二)
上一篇简单的对轻量级ORM开发开了个头.这篇主要聊下ORM框架的设计思路. ORM本质上是对数据库操作的抽象.大体上我将其分为对数据结构的抽象和对执行方法的抽象. 我的ORM设计图: ORM框架需要完 ...
- FastAPI项目实战:"异步"接口测试"平台"
apiAutoTestWeb 是什么? apiAutoTest接口自动化测试工具的可视化版本,将原本对用例的操作转移到Web页面之上 用什么实现? 接口自动化测试:大体上测试逻辑将采用apiAutoT ...
- FastAPI + Vue 前后端分离 接口自动化测试工具 apiAutoTestWeb
apiAutoTestWeb使用说明 apiAutoTestWeb是为apiAutoTest的可视化版本,其采用前后端分离(FastAPI + Vue2)方式实现 具体使用: Python3 + Fa ...
随机推荐
- linux配置maven
1.下载mavenhttps://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/ 中找到相应的版本wget https://mirrors.tun ...
- 基于iscsi存储池
命令行 [root@kvm1 ~]# virsh pool-define-as --name stor2 --type iscsi \ > --source-host 192.168.114.1 ...
- flutter ios 深色模式下状态栏文字是白色的,白色背景下看不见
flutter ios 深色模式下状态栏文字是白色的,白色背景下看不见 theme: ThemeData( appBarTheme: const AppBarTheme( systemOverlayS ...
- 最新demo版 | 如何0-1开发支付宝小程序之小程序如何上线(四)
支付宝小程序开发 0-1 系列前三期详见: 最新demo版|如何0-1开发支付宝小程序之前期准备篇(一) 最新demo版 | 如何0-1开发支付宝小程序之如何调试小程序(二) 最新demo版 | 如何 ...
- Java轻量级代码工程
一.背景简介 最近2年,很多公司接项目开始不挑剔了,只要核算下来有收益不会亏,就会库库的做各种没头没脑的项目,都是抱着多撑一天是一天的躺平心态. 如果项目和业务稳定,自然也有动力卷架构卷设计. 然而2 ...
- 使用browser-use进行数据爬取实战记录
前言 前面的文章介绍了browser-use的基本使用,今天带来的分享是使用browser-use进行一次数据爬取的实战(不过还是demo级别的). 使用到的三个玩法分别是使用自己的浏览器.定义输出结 ...
- 微信小程序如何访问带有Token安全认证的API
展开微信小程序访问Token安全验证的API接口API//添加一个自定义过滤器using Newtonsoft.Json;using System;using System.Collections.G ...
- 【ABAQUS 二次开发笔记】一次获得多个积分点的输出到dat
当使用shell单元进行composite laminate 建模时,可以为每一指定Intergration point 的个数,默认是3个.(abaqus有很多variable可以在intergra ...
- idle如何调试程序
1.启动idle ctrl+n 快捷键 新建命令窗口 输入程序 4.F5 调试程序,结果看在启动界面查看
- 如何基于大语言模型和MaxKB实现PPT自动生成方案
一.实现方案 利用讯飞大模型智能 PPT 生成接口实现,具体参见:讯飞开放平台智能PPT生成 https://www.xfyun.cn/services/aippt#anchor4503211 二.新 ...