Tortoise-ORM集成(1)
查询参数查询参数是URL中?后面的键值对组合格式为key1value1key2value2用于对资源进行「筛选、分页、排序」等辅助操作。eg: /users?name张三age20name姓名、age年龄是查询参数对比维度路径参数查询参数位置URL路径中/items/{item_id}URL后缀?skip0limit10必要性必填默认可选默认可设置必填核心用途标识唯一资源如ID、UID筛选、分页、排序等辅助操作配置工具Path类Query类示例场景/items/1、/users/100/items?limit10、/users?name张三# 1. 字符串查询参数搜索关键词 app.get(/search/items/, summary字符串查询参数校验) def search_items( q: str | None Query( None, # 默认None可选 min_length1, max_length100, patternr^[^#$%^*]$, # 禁止包含特殊字符#$%^* description搜索关键词1-100位禁止包含#$%^* ) ): if not q: return {code: 200, message: 请输入搜索关键词} return {code: 200, message: f搜索「{q}」成功, data: []} # 2. 数值查询参数价格筛选 app.get(/filter/products/, summary数值查询参数校验) def filter_products( min_price: float Query(0.0, ge0.0, description最低价格≥0), max_price: float Query(1000.0, le1000.0, description最高价格≤1000) ): return { code: 200, filter: f价格区间{min_price} - {max_price}, message: 筛选产品成功 } # 3. 别名参数解决前端传参命名规范问题 app.get(/pages/, summaryQuery别名参数示例) def get_pages( page: int Query(1, ge1, description页码), # 后端参数名page_size前端传page-size中划线命名 page_size: int Query(20, ge1, le50, aliaspage-size, description每页条数) ): return { code: 200, page: page, page_size: page_size, message: 分页查询成功 }由此课间Query查询参数是写在def方法括号里可以是关键字分页等多种方式查询也可以进行组合中间用‘’隔开查询参数一般都是选填可有可无如果是必传的情况可以在条件之前加上“...”表示必填如下所示app.get(/users/filter/, summary必选查询参数) def filter_users( # 必选查询参数必须传入username否则报错 username: str Query( ..., # ... 表示必填无默认值 min_length3, max_length20, description用户名必填3-20位字符 ), # 可选查询参数年龄 age: int | None Query(None, ge1, le120, description年龄可选) ): result {code: 200, username: username, message: 筛选用户成功} if age: result[age] age return result请求体前端要一次性传一堆信息比如新增用户用户名、邮箱、密码、年龄这么多参数塞网址里不现实所以把所有数据打包放在请求体body里发给后端这部分打包的数据就叫请求体。BaseModelField提前定义好前端必须传什么、每个数据有什么规则前端传错自动返回提示不用自己写 if 判断校验。# 带字段校验的用户注册模型 class UserCreateWithValidate(BaseModel): 带字段校验的用户注册请求体模型 # 用户名3-20位仅字母/数字/下划线必填 username: str Field( ..., # 必填字段 min_length3, max_length20, patternr^[a-zA-Z0-9_]$, title用户名, description3-20位仅支持字母、数字、下划线, examplezhangsan_123 ) # 邮箱符合邮箱格式必填 email: str Field( ..., patternr^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}$, title邮箱, description请输入合法的邮箱地址, examplezstest.com ) # 密码6-20位必填 password: str Field( ..., min_length6, max_length20, title密码, description6-20位字符建议包含字母和数字, example123456a ) # 年龄1-120岁可选默认None age: int | None Field( None, ge1, le120, title年龄, description1-120岁之间, example25 ) # 带校验的注册接口 app.post(/users/register/validate/, summary带字段校验的注册接口) def user_register_validate(user_info: UserCreateWithValidate): return { code: 200, message: 注册成功带字段校验, data: { username: user_info.username, email: user_info.email, age: user_info.age or 未填写 } }Tortoise-ORM 模型定义常用字段类型速查表字段类型Python 类型数据库类型说明fields.IntField(pkTrue)intINT AUTO_INCREMENT自增主键fields.CharField(max_lengthN)strVARCHAR(N)可变长字符串fields.TextField()strTEXT长文本fields.BooleanField(defaultTrue)boolBOOL/TINYINT布尔值fields.DatetimeField(auto_now_addTrue)datetimeDATETIME创建时间自动填充fields.DatetimeField(auto_nowTrue)datetimeDATETIME更新时间自动更新fields.DecimalField(max_digits, decimal_places)DecimalDECIMAL精确小数用于金额fields.FloatField()floatFLOAT浮点数fields.JSONField()dict/listJSONJSON 数据fields.ForeignKeyField()FOREIGN KEY外键一对多fields.OneToOneField()关联模型FOREIGN KEY UNIQUE一对一关系fields.ManyToManyField()关联模型中间表多对多关系实操查task_router.get(/all,summary获取所有任务) async def get_all_tasks( keyword:str|NoneQuery(None,description搜索关键词), sort_by_priority: bool Query(True, description按优先级排序) ): queryTask.all() if keyword: queryquery.filter(Q(title__icontainskeyword)) if sort_by_priority: queryquery.order_by(-priority) else: queryquery.order_by(id) infoawait query return { msg:ok, code:200, data:info }在def 方法里加了query参数做条件查询query Task.all()仅拼接查询条件获取到符合条件的数据之后在进行过滤最后await才执行真正的SQL从数据库拿到任务列表数据。注意不能提前写 Task.all()Task.all()一旦提前 cawait变量变成 list后面filter/order_by会直接报错。增task_router.post(/add,summary添加任务) async def add_task(task:TaskAdd): infoawait Task.create(**dict(task)) return { msg:ok, code:200, data:info }class TaskAdd(BaseModel): user_id:intField( ..., title用户ID, description用户ID, example1 ) title:strField( ..., title任务标题, description任务标题, example学习 ) description:strField( None, title任务描述, description任务描述, example学习Python ) status:intField( 0, title任务状态, description任务状态, example0 ) priority:intField( 1, title任务优先级, description任务优先级, example1 ) due_date:strField( None, title任务截止时间, description任务截止时间, example2023-05-01 ) completed_at:strField( None, title任务完成时间, description任务完成时间, example2023-05-01 ) created_at:strField( None, title任务创建时间, description任务创建时间, example2023-05-01 ) updated_at:strField( None, title任务更新时间, description任务更新时间, example2023-05-01 )在Basemodel中接受前端传过来的参数“...”表示必传None表示可有可无。然后新增核心语句infoawait Task.create(**dict(task))dict(task)将模型对象转为标准字典**是字典解包将键值对平铺传入create方法改task_router.put(/update/{id},summary更新任务) async def update_task(id:int ,task:TaskUpdate): infoawait Task.filter(idid).update(**dict(task)) return { msg:ok, code:200, data:info }直接获取到当前要修改的id的数据进行更新与增加同理在basemodel中获取前端要传的参数与之不同的是basemodel中所有此参数都是None可有可无。对于不存在的id也不会抛出异常也会显示修改成功对于部分修改以状态为例task_router.put(/{id}/status,summary改变状态) async def change_task_status(id:int,task:TaskChangeStatus): infoawait Task.filter(idid).update(**dict(task)) return { msg:ok, code:200, data:info }class TaskChangeStatus(BaseModel): status:intField( ..., title任务状态, description任务状态, example0 )只需要在basemodelzhong写要修改的字段即可这样就只能修改约定好的字段删task_router.delete(/delete/{id},summary删除任务) async def delete_task(id:int): infoawait Task.filter(idid).delete() return { msg:ok, code:200, data:info }删除只需要传要删除的id即可这里也是最简单的方法如果对于不存在的id也会返回删除成功实际上不存在的数据执行删除也没有意义因此加不加判断意义不大存在的直接删除。总结这里主要是对ORM 增删改查查询需先拼接 QuerySet 条件最后 await 避免列表报错新增用Task.create(**dict(模型))、修改用filter().update()、删除用filter().delete()局部修改可精简请求体模型仅保留允许更新的字段。其中对于新增修改等需要常用请求体传参的方法需要在basemodel中阐明相关字段是必须传...还是可穿可不穿None。当然方法不应该固化成一种有许多种方法实现尤其是新增还有很多实用的方法。

相关新闻

C++的基本概念

C++的基本概念

‌C基础概念主要围绕语法基础、面向对象特性和内存管理三大块展开‌,它既支持C语言的过程化编程,也能进行面向对象编程,还能玩泛型编程,是个“多面手”。‌‌ 百科‌📚 入门得先搞懂啥 ‌基本数据类型‌:最…

2026/10/7 0:23:44 阅读更多 →
Linux Mint 22.3 Zena:新手首选Linux发行版体验与优化指南

Linux Mint 22.3 Zena:新手首选Linux发行版体验与优化指南

1. Linux Mint 22.3 Zena 初体验:为什么它是新手的最佳选择作为一个长期在老旧笔记本上折腾各种Linux发行版的用户,当我第一次启动Linux Mint 22.3 Zena时,那种流畅感让我瞬间理解了为什么它被称为"最适合新手的Linux"。Zena基于Ub…

2026/10/6 0:46:59 阅读更多 →
IDEA工具使用

IDEA工具使用

IDEA 工具使用(较新版本与旧版本区别及使用说明) 从 2017 直接跳到 2025,跨度 8 年,界面焕然一新但核心操作没变。这篇笔记整理了两个版本的全方位对比,以及新版创建各类项目的详细步骤和踩过的坑。 一、整体界面&…

2026/10/12 20:07:29 阅读更多 →

最新新闻

宠物咖啡馆平台实战:SpringBoot2+Vue3前后端分离全解析

宠物咖啡馆平台实战:SpringBoot2+Vue3前后端分离全解析

宠物咖啡馆这几年开得到处都是,但真去体验过运营节奏的人都知道:吧台排队点单、撸猫时段预约、宠物当天的接待状态全靠店员脑子硬记,人一多就乱套。我最近完整跑通并整理了一套宠物咖啡馆平台,技术栈是很多人点过名的 SpringBoot2…

2026/10/13 11:52:33 阅读更多 →
机器学习调参指南:从欠拟合过拟合诊断到网格搜索

机器学习调参指南:从欠拟合过拟合诊断到网格搜索

先说个我常遇到的场景:调参调了半天,模型就是“学不进去”,训练集和测试集得分都不高;或者训练集上几乎完美命中,一到新数据就崩。这两种情形分别对应欠拟合和过拟合,大部分人第一反应是加数据、加正则、换…

2026/10/13 11:52:33 阅读更多 →
操作系统磁盘管理小测复盘:从LBA寻址到调度算法与缓冲机制

操作系统磁盘管理小测复盘:从LBA寻址到调度算法与缓冲机制

这学期操作系统课讲到设备管理章节的时候,老师突然在课程平台上挂了一张随堂小测,标题是“设备管理之磁盘”。我一开始真没当回事,觉得磁盘嘛,从文件系统到分区到格式化,平时都接触过,考不出什么花来。结果…

2026/10/13 11:52:33 阅读更多 →
Zemax实战:单模光纤耦合效率如何从估算到精准仿真

Zemax实战:单模光纤耦合效率如何从估算到精准仿真

简介:这是一份Zemax模拟单模光纤光束耦合的完整范例文档,主要面向从事光纤通信、光器件设计的光学工程师,也适合正在学习Zemax软件的分析人员。文档以SUSS MicroOptics FC-Q-250微透镜阵列作为核心元件,演示如何将两根康宁SMF-28e…

2026/10/13 11:52:33 阅读更多 →
Android面试实战复盘:从核心技术到项目表达的系统指南

Android面试实战复盘:从核心技术到项目表达的系统指南

1. 先聊聊我对Android面试的整体认知做了这么多年Android开发,大大小小的面试参加过不少,也以面试官的身份坐在桌子对面看过形形色色的候选人。说实话,我越来越觉得,有开发经验的人去面试,和应届生去面试,完…

2026/10/13 11:52:33 阅读更多 →
EmguCV单目相机标定与畸变校正实战:从棋盘格到参数应用

EmguCV单目相机标定与畸变校正实战:从棋盘格到参数应用

做机器视觉项目的人,十有八九会在第一步被镜头畸变坑一回。标定板明明贴得很正,拍出来的直线却带着弧度;视野中心量得好好的,一到画面边缘工件形状就走样。这个问题的标准解法,就是用棋盘格做一次相机标定,…

2026/10/13 11:51:32 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →