ORM项目搭建
第一部分Tortoise-ORM集成ORM 的概念ORM 全称是 Object-Relational Mapping对象关系映射 。它的核心思想是用 Python 类来代表数据库中的表用类的实例来代表表中的一行记录同步 ORM vs 异步 ORM 对比如代码所示# 同步写法Django ORMuserUser.objects.get(id1)postsPost.objects.filter(authoruser)# 异步写法Tortoise-ORM—— 注意 await 关键字userawaitUser.get(id1)postsawaitPost.filter(authoruser)第二部分环境搭建与 FastAPI 集成基于 MySQL# 安装 Tortoise-ORM 核心库pip install tortoise-orm#MySQL 异步驱动推荐 asyncmypip install asyncmy 或者 pip install aiomysql# 安装 Aerich 迁移工具后面会用到pip install aerich# 安装 FastAPI 和 Uvicornpip install fastapiuvicorn[standard]项目结构规划数据库配置文件app/config.pypythonapp/config.py“”数据库配置文件这个文件定义了 Tortoise-ORM 连接 MySQL 数据库所需的所有配置信息“”TORTOISE_ORM 是 Tortoise-ORM 规定的配置字典变量名后面用 register_tortoise 或 Aerich 时都会引用这个字典TORTOISE_ORM {# 1. 连接配置 —— 定义数据库连接信息“connections”: {# “default” 是默认连接的名字必须有一个 default“default”: {# engine指定数据库后端引擎MySQL 使用 tortoise.backends.mysql“engine”: “tortoise.backends.mysql”,# credentials数据库连接凭证包含主机、端口、用户名、密码等 credentials: { host: 127.0.0.1, # MySQL 服务器地址 port: 3306, # MySQL 端口默认 3306 user: root, # 数据库用户名 password: 123456, # 数据库密码请根据实际情况修改 database: fastapi_db1, # 数据库名称 minsize: 1, # 连接池最小连接数 maxsize: 5, # 连接池最大连接数 charset: utf8mb4, # 字符集支持 emoji echo: True # 是否打印 SQL 语句开发环境建议开启 } } }, # 2. 应用配置 —— 指定模型所在的模块 apps: { # models 是应用的名字可以自定义但 Aerich 需要使用这个名字 models: { # models 列表指定包含 Tortoise 模型类的 Python 模块路径 # aerich.models 是 Aerich 的内置模型用于记录迁移历史必须包含 models: [app.models, aerich.models], # default_connection指定这个应用使用哪个数据库连接 default_connection: default, } }, # 3. 时区配置 use_tz: False, # 是否使用时区 timezone: Asia/Shanghai # 时区设置}FastAPI 主应用app/main.pyfromfastapiimportFastAPI,Query,HTTPExceptionfrompydanticimportField,BaseModelfromstarlette.requestsimportRequestfromstarlette.responsesimportJSONResponsefromtortoiseimportTortoisefromtortoise.contrib.fastapiimportregister_tortoisefromapp.configimportTORTOISE_ORMfromapp.routers.userimportuser_router appFastAPI()register_tortoise(appapp,configTORTOISE_ORM,generate_schemasTrue,add_exception_handlersTrue)第三部分完整项目流程Model模型搭建fromtortoiseimportmodels,fieldsclassUser(models.Model):idfields.BigIntField(pkTrue)usernamefields.CharField(max_length50,verbose_name用户名)passwordfields.CharField(max_length50,verbose_name密码)classMeta:tablet_usertable_description用户表classTask(models.Model):idfields.BigIntField(pkTrue)user_idfields.BigIntField(verbose_name所属用户)titlefields.CharField(max_length50,verbose_name任务标题)descriptionfields.TextField(nullTrue,verbose_name任务描述)statusfields.SmallIntField(default0,verbose_name任务状态)priorityfields.SmallIntField(default1,verbose_name任务优先级)due_datefields.DatetimeField(nullTrue,verbose_name任务截止日期)completed_atfields.DatetimeField(nullTrue,verbose_name完成时间)created_atfields.DatetimeField(auto_now_addTrue)updated_atfields.DatetimeField(auto_nowTrue)classMeta:tablet_tasktable_description任务表查询数据routers:fromdatetimeimportdatetimefromtypingimportListfromfastapiimportAPIRouter,Queryfromapp.models.bookimportUser,Taskfromapp.schemas.bookimportUserLoginRequest,TaskSchema,TaskResponse,TaskList,TaskCreate,TaskUpdate,TaskStatus user_routerAPIRouter(prefix/user,tags[用户])user_router.post(/login,summary登录,description登录)asyncdeflogin(user_login:UserLoginRequest):userawaitUser.filter(usernameuser_login.username).first()ifuserisNone:return{code:0,message:用户不存在}ifuser.password!user_login.password:return{code:0,message:密码错误}return{code:1,message:登陆成功}task_routerAPIRouter(prefix/task,tags[任务])task_router.get(/list,response_modelList[TaskResponse],summary任务列表筛选)asyncdeftask_list(query:TaskListQuery()):infoTask.filter(user_id1)ifquery.statusandquery.status!all:infoinfo.filter(statusint(query.status))ifquery.keyword:infoinfo.filter(title__containsquery.keyword)ifquery.sort_priorityasc:infoinfo.order_by(-priority)else:infoinfo.order_by(priority)returnawaitinfotask_router.post(/add,response_modelTaskResponse,summary新增任务)asyncdeftask_add(data:TaskCreate):taskawaitTask.create(**data.model_dump())returntasktask_router.delete(/delete/{id},summary删除任务,description删除任务)asyncdeftask_delete(id:int):awaitTask.filter(idid).delete()return{code:1,message:删除成功}task_router.put(/update/{id},summary更新用户,description更新用户)asyncdefupdate_task(task:TaskUpdate,id:int):print(dict(task))task1awaitTask.get_or_none(idid)iftask1isNone:return{code:0,message:task not found}task_dicttask.model_dump(exclude_unsetTrue)awaitTask.filter(idid).update(**task_dict)return{code:1,message:update success}task_router.put(/{id}/status/,summary更新任务状态,description快速切换任务状态自动处理完成时间)asyncdefupdate_task_status(body:TaskStatus,id:int):task1awaitTask.get_or_none(idid)iftask1isNone:return{code:0,message:task not found}update_databody.model_dump(exclude_unsetTrue)new_statusupdate_data.get(status)ifnew_status2:update_data[completed_at]datetime.now()else:update_data[completed_at]NoneawaitTask.filter(idid).update(**update_data)return{code:1,message:status update success}schemas:fromdatetimeimportdatetimefromtypingimportListfromfastapiimportAPIRouter,Queryfromapp.models.bookimportUser,Taskfromapp.schemas.bookimportUserLoginRequest,TaskSchema,TaskResponse,TaskList,TaskCreate,TaskUpdate,TaskStatus user_routerAPIRouter(prefix/user,tags[用户])user_router.post(/login,summary登录,description登录)asyncdeflogin(user_login:UserLoginRequest):userawaitUser.filter(usernameuser_login.username).first()ifuserisNone:return{code:0,message:用户不存在}ifuser.password!user_login.password:return{code:0,message:密码错误}return{code:1,message:登陆成功}task_routerAPIRouter(prefix/task,tags[任务])task_router.get(/list,response_modelList[TaskResponse],summary任务列表筛选)asyncdeftask_list(query:TaskListQuery()):infoTask.filter(user_id1)ifquery.statusandquery.status!all:infoinfo.filter(statusint(query.status))ifquery.keyword:infoinfo.filter(title__containsquery.keyword)ifquery.sort_priorityasc:infoinfo.order_by(-priority)else:infoinfo.order_by(priority)returnawaitinfotask_router.post(/add,response_modelTaskResponse,summary新增任务)asyncdeftask_add(data:TaskCreate):taskawaitTask.create(**data.model_dump())returntasktask_router.delete(/delete/{id},summary删除任务,description删除任务)asyncdeftask_delete(id:int):awaitTask.filter(idid).delete()return{code:1,message:删除成功}task_router.put(/update/{id},summary更新用户,description更新用户)asyncdefupdate_task(task:TaskUpdate,id:int):print(dict(task))task1awaitTask.get_or_none(idid)iftask1isNone:return{code:0,message:task not found}task_dicttask.model_dump(exclude_unsetTrue)awaitTask.filter(idid).update(**task_dict)return{code:1,message:update success}task_router.put(/{id}/status/,summary更新任务状态,description快速切换任务状态自动处理完成时间)asyncdefupdate_task_status(body:TaskStatus,id:int):task1awaitTask.get_or_none(idid)iftask1isNone:return{code:0,message:task not found}update_databody.model_dump(exclude_unsetTrue)new_statusupdate_data.get(status)ifnew_status2:update_data[completed_at]datetime.now()else:update_data[completed_at]NoneawaitTask.filter(idid).update(**update_data)return{code:1,message:status update success}这是一个任务表与用户表格的接口效果实现如图下面是用户表的登录接口效果展示下面是任务表格的查询接口展示下面是给任务表格添加数据的效果下面是对任务表格数据修改的展示下面是对任务表格数据删除的展示下面是对任务表格状态的修改的展示以上也就是用orm对数据的增删改查的功能展示他的用法跟django的语法类似

相关新闻

驱动电路维修:ULN2003与L298N故障排查实战

驱动电路维修:ULN2003与L298N故障排查实战

1. 驱动电路维修入门:从菜鸟到能手的必经之路 第一次遇到小信号推不动负载的问题时,我正面对着一台罢工的自动售货机。控制板上的指示灯正常闪烁,但电机纹丝不动。这种"信号有但带不动"的故障,在驱动电路维修中极为常见…

2026/7/22 14:17:45阅读更多 →
树莓派4B安装Ubuntu Server 20.04 LTS全攻略

树莓派4B安装Ubuntu Server 20.04 LTS全攻略

1. 为什么选择Ubuntu Server 20.04 for Raspberry Pi 当我在2020年第一次尝试将Ubuntu Server 20.04刷入树莓派4B时,完全没想到这个组合会成为嵌入式开发者的黄金标准。与常见的Raspbian(现称Raspberry Pi OS)相比,Ubuntu Server提…

2026/7/21 23:35:00阅读更多 →
Lens-3.8B-bf16 vs Stable Diffusion:Apple Silicon上的终极性能对比测试

Lens-3.8B-bf16 vs Stable Diffusion:Apple Silicon上的终极性能对比测试

Lens-3.8B-bf16 vs Stable Diffusion:Apple Silicon上的终极性能对比测试 【免费下载链接】Lens-3.8B-bf16 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Lens-3.8B-bf16 在Apple Silicon平台上选择合适的大语言模型进行文本到图像生成时&am…

2026/7/21 23:19:40阅读更多 →
070、TensorFlow Lite Micro的Deployment项目:部署到生产环境

070、TensorFlow Lite Micro的Deployment项目:部署到生产环境

070 TensorFlow Lite Micro的Deployment项目:部署到生产环境 昨晚凌晨两点,我在产线上盯着那块STM32U5开发板,串口输出突然卡死在“AllocateTensor failed”上。旁边测试工程师递来一杯冷掉的咖啡,说“这板子上午还跑得好好的”。我盯着调试器里那个0xDEADBEEF的地址,突然…

2026/7/22 14:20:22阅读更多 →
泉州不住家阿姨哪家实力强

泉州不住家阿姨哪家实力强

在泉州生活节奏越来越快的今天,不少家庭开始考虑请一位不住家阿姨,既能分担家务、照顾老人孩子,又不必占用家中多余房间。但面对市场上良莠不齐的家政公司,很多人都会问:泉州不住家阿姨到底哪家更靠谱? 今天…

2026/7/22 14:20:22阅读更多 →
069、TensorFlow Lite Micro的Testing项目:测试与验证

069、TensorFlow Lite Micro的Testing项目:测试与验证

069 TensorFlow Lite Micro的Testing项目:测试与验证 昨晚调试一块STM32U5板子,模型推理结果死活不对——输出全是0.0。折腾到凌晨两点,最后发现是测试用例没跑通,模型量化参数在PC端和MCU端对不上。这种坑,我猜你也踩过。 TFLM的Testing项目,很多人以为只是“跑个单元…

2026/7/22 14:20:22阅读更多 →
如何在PS4上轻松管理1490+游戏金手指:GoldHEN金手指管理器完全指南

如何在PS4上轻松管理1490+游戏金手指:GoldHEN金手指管理器完全指南

如何在PS4上轻松管理1490游戏金手指:GoldHEN金手指管理器完全指南 【免费下载链接】GoldHEN_Cheat_Manager GoldHEN Cheats Manager 项目地址: https://gitcode.com/gh_mirrors/go/GoldHEN_Cheat_Manager 还在为PS4游戏难度过高而苦恼吗?是否曾经…

2026/7/22 14:20:22阅读更多 →
Codex AI编程助手:从安装配置到企业级部署

Codex AI编程助手:从安装配置到企业级部署

1. Codex初识:AI编程助手的核心能力解析第一次接触Codex时,我被它"用自然语言生成代码"的能力震撼到了。这个由OpenAI打造的AI编程助手,本质上是一个经过海量代码训练的语言模型,能够理解开发者用日常英语描述的需求&am…

2026/7/22 14:20:22阅读更多 →
嵌入式系统开发及应用(高级)交互式教程

嵌入式系统开发及应用(高级)交互式教程

嵌入式系统开发及应用(高级)交互式教程 概述 本教程是《嵌入式系统开发及应用》系列的最高级别,面向具备中级嵌入式开发能力的工程师。内容涵盖系统架构设计、网络通信、无线技术、GUI开发、电机控制、Linux应用、多媒体处理、OTA远程管理、测…

2026/7/22 14:18:21阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →