当前位置: 首页 > news >正文

后端(FastAPI)学习笔记(CLASS 3):Tortoise ORM

Tortoise ORM是一个易于使用的ORM(对象关系映射器),灵感来自于Django

python有许多现有和成熟的ORM,不幸的是,它们的设计方式与I/O处理方式相反,是相对较新的技术,具有不同的并发模型,最大的变化是关于I/O的处理方式

一般为:数据表对应模型类,字段对应类属性,字段约束对应类的属性值,表记录对应模型类的实例

一、模型定义

1、基本使用

在tortoise ORM中,定义模型类似于Django ORM。我们定义一个模型类,并继承自Model类。下面是一个简单的模型定义实例,包括字段类型和关系

1、安装tortoise ORM:

pip install tortoise-rom

pip install tortoise-orm[asyncmy]

2、配置tortoise ORM

在项目入口文件中配置Tortoise ORM,例如在main.py中:

from tortoise import Tortoise, run_asyncasync def init():await Tortoise.init(db_url='mysql://root:mysql@localhost:3306/library-management',modules={'models': ['__main__']})await Tortoise.generate_schemas()run_async(init())

3、定义模型

假设我们有User和Post模型,其中User和Post之间是一对多的关系

2、字段类型

Tortoise ORM 提供了多种字段类型,以下是一些常用的字段类型:

IntField整数字段
CharField字符字段
TextField文本字段
BooleanField布尔字段
DateField日期字段
DatetimeField日期时间字段
FloatField浮点数字段
3、关系类型

一对多(ForeignKeyField)

多对多(ManyToManyField)

一对一(OneToOneField)

1、一对多关系

一个用户可以有多个帖子:

# 定义一个用户表(用户模型)
# 1个用户 ---> 可以发布多篇文章
class UserModel(Model):id = fields.IntField(primary_key=True, description="用户id")nickname = fields.CharField(max_length=255, description="用户昵称")username = fields.CharField(max_length=255, description="用户名")password = fields.CharField(max_length=255, description="用户密码")# 或者# posts = fields.ReverseRelation["PostModel"]def __str__(self):return self.nicknameclass Meta:table = "user"table_description = "用户表"class PostModel(Model):"""帖子表"""id = fields.IntField(primary_key=True, description="用户id")title = fields.CharField(max_length=255, description="帖子标题")content = fields.CharField(description="帖子内容")user = fields.ForeignKeyField("models.UserModel", related_name="posts", description="用户id")def __str__(self):return self.titleclass Meta:table = "Post"table_description="帖子表"

2、一对一的关系

一个用户对应一个用户详情

# 定义一个用户详细信息表
# 1个用户 ---> 1个用户信息
class UserInfoModel(Model):id = fields.IntField(primary_key = True, description = "用户信息id")age = fields.IntField(desciption="年龄")sex = fields.CharField(max_length=255, description="性别")user = fields.OneToOneField("models.UserModel", related_name="user_info", description="用户id")def __str__(self):return self.user.nickname

3、多对多的关系

多个用户对应多个社群

# 定义一个社群表
# 1个用户可以加入多个社群
# 1个社群有多个用户class CommunityModel(Model):id = fields.IntField(primary_key=True, description="社群id")name = fields.CharField(max_length=255, description="社群名称")user = fields.ManyToManyField("models.UserModel", related_name="communities", description="用户id")

二、基础查询语法

当然,以下是Tortoise ORM中关联模型查询的详细语法,包括一对多、多对一、多对多等情况的示例

1、模型定义

首先,我们定义几个示例模型

如上代码

2、以下为整体附带创建数据的方法:
from tortoise import Tortoise, Model, fields, run_async"""
模型类型的设计:1、定位继承tortoise.models.Model类2、在模型类中定义字段字段的属性是tortoise.fields中的字段类型
"""# 定义一个用户表(用户模型)
# 1个用户 ---> 可以发布多篇文章
class UserModel(Model):id = fields.IntField(primary_key=True, description="用户id")nickname = fields.CharField(max_length=255, description="用户昵称")username = fields.CharField(max_length=255, description="用户名")password = fields.CharField(max_length=255, description="用户密码")# 或者# posts = fields.ReverseRelation["PostModel"]def __str__(self):return self.nicknameclass Meta:table = "user"table_description = "用户表"class PostModel(Model):"""帖子表"""id = fields.IntField(primary_key=True, description="用户id")title = fields.CharField(max_length=255, description="帖子标题")content = fields.CharField(max_length=255, description="帖子内容")user = fields.ForeignKeyField("models.UserModel", related_name="posts", description="用户id")def __str__(self):return self.titleclass Meta:table = "Post"table_description="帖子表"# 定义一个用户详细信息表
# 1个用户 ---> 1个用户信息
class UserInfoModel(Model):id = fields.IntField(primary_key = True, description = "用户信息id")age = fields.IntField(description="年龄")sex = fields.CharField(max_length=255, description="性别")user = fields.OneToOneField("models.UserModel", related_name="user_info", description="用户id")def __str__(self):return self.user.nickname# 定义一个社群表
# 1个用户可以加入多个社群
# 1个社群有多个用户class CommunityModel(Model):id = fields.IntField(primary_key=True, description="社群id")name = fields.CharField(max_length=255, description="社群名称")user = fields.ManyToManyField("models.UserModel", related_name="communities", description="用户id")async def create_data():# 创建数据:模型类.create()user = await UserModel.create(nickname="张三", username="zhangsan", password="123456")userinfo = await UserInfoModel.create(age=18, sex="男", user=user)print(user, userinfo)async def init():# 初始化连接数据库配置await Tortoise.init(db_url='mysql://root:20050824@localhost:3306/test',modules={'models': ['__main__']})await create_data()# 在数据库中创建表# await Tortoise.generate_schemas()if __name__ == '__main__':run_async(init())
3、以下为查询语法:
async def find_all_user():# all: 获取所有数据users = await UserModel.all()for user in users:print(user)# filter: 过滤所有数据users = await UserModel.filter(id=1)for user in users:print(user)# get: 获取单条数据,数据不存在会报错user = await UserModel.get(id=1)print(user.__dict__['nickname'])# get_or_none: 获取单条数据,数据不存在则返回空
4、以下为更新语法:
async def update_user():# 方式一: 根据对象.update_from_dictuser = await UserModel.get(id=1)user = await user.update_from_dict({"nickname": "张三2","username": "zhangsan","password": "123456"})# 修改完要用save函数保存# 方式二: 根据对象.属性=值user = await UserModel.get(id=1)user.nickname = '老张呀'await user.save()print(user.__dict__)# 查询集的update方法await UserModel.filter(id=1).update(nickname="老张")
5、以下为删除语法:
async def delete_user():# 方式一: 使用查询集的delete方法, 进行批量删除await UserModel.filter(id=1).delete()# 方式二: 使用模型对象的delete方法,进行单个删除user = await UserModel.get(id=1)await user.delete()

三、关联查询

1、一对一关联查询

从User获取UserInfo的信息

# 一对一关联查询的使用
async def one_to_one_query():user = await UserModel.get(id = 1).prefetch_related('user_info')if user and hasattr(user, "user_info"):print(user.user_info.address)
2、一对多关联查询

从User获取Post

async def get_user_posts(user_id: int):user = await UserModel.get(id=user_id).prefetch_related('posts')posts = await user.posts.all().values("id", "title", "content")print(f"User: {user.nickname}, Posts: {posts}")
3、多对一关联查询

通过Post获取User

# 多对一关联查询的使用
async def many_to_one_query():post = await PostModel.get(id=1).prefetch_related("user")if post and hasattr(post, "user"):result = {"id": post.id,"title": post.title,"content": post.content,"user": {"id": post.user.id,"nickname": post.user.nickname}}print(result)
4、多对多关联查询

从User中获取Community

# 多对多的查询
async def many_to_mant_query():user = await UserModel.get(id=1).prefetch_related("communities")if user and hasattr(user, "communities"):communities = []for community in user.communities:communities.append({"id": community.id,"name": community.name})result = {"id": user.id,"nickname": user.nickname,"communities": communities}print(result)

反过来也是一样的

四、高级查询

1、排序

获取特定用户及其所有帖子,并根据帖子标题排序

# 排序查询
async def sort_user_all():users = await UserModel.all().order_by("id").values("id", "nickname", "username")print(users)
2、过滤查询

获取某个过滤条件下所需的信息

# 排序查询
async def sort_user_all():users = await UserModel.filter(id__gt=1).values("id", "nickname", "username")print(users)

gt(大于)、lt(小于)、gte(大于等于)、lte(小于等于)

icontains(包含)

3、分页查询

获取用户的所有帖子,并进行分页(每页显示5条记录):

# 分页查询"""offset方法:指定数据获取的起始位置limit方法:指定每页返回多少条数据"""
async def limit_page_user_all(page, size):user = await UserModel.all().offset((page - 1) * size ).limit(size)print(user)
4、聚合查询

在查询的信息中返回总数,平均数等信息

from tortoise.functions import Count, Avg, Max, Min# 聚合查询
async def annotate_query():user = await UserModel.annotate(post_count = Count("posts")).all()
5、自定义sql查询

有时候你可能需要执行原始SQL查询,Tortoise ORM也提供了支持。使用了Tortoise.get_connection().execute_query_dict()方法执行原始SQL查询,并获取结果

async def execute_raw_sql() -> None:# 获取数据库连接对象db = Tortoise.get_connection('defalut')# 执行查询语句并返回字典users = await db.execute_query_dict("select * from user")print(users)
* 总结

1、按条件查询:使用filter方法添加查询条件

2、排序:使用order_by方法对查询结果进行排序

3、分页:使用offset和limit方法进行分页查询

4、关联查询:使用prefetch_related或select_related方法进行关联查询

5、聚合查询:使用annotate进行联合查询

五、数据库迁移

1、generate_schemas

tortoise ORM自带的generate_schemas方法进行迁移

2、使用Aerich

tortoise ORM自带的generate_schemas方法是为了快速开发时使用的,它会在数据库中创建所有必要的表结构,但不使用于生产环境的数据迁移。为了进行更复杂的数据库迁移,推荐使用第三方工具Alembic

安装Aerich:

pip install aerich

迁移配置:

# 关于tortoise的配置
TORTOISE_ORM = {'connections': {'default': {'engine': 'tortoise.backends.mysql','credentials': {'host': 'localhost','port': '3306','user': 'root','password': '20050824','database': 'demo'}}},'apps': {'models': {'modesl': ['aerich.models', '4.6transform'],'default_connection': 'default'}}
}# 注册ORM模型
register_tortoise(app, config=TORTOISE_ORM)

迁移命令:

在项目根目录运行一下命令:

aerich init -t main.TORTOISE_ORM

其中app.TORTOISE_ORM是Tortoise ORM的配置路径。例如,如果Tortoise配置在main.py中,配置路径可以是main.TORTOISE_ORM

生成迁移文件,初始化数据库:

aerich init -db

每次修改模型后,运行以下命令生成迁移文件:

aerich migrate

应用迁移:

aerich upgrade


文章转载自:

http://XBBAAkdu.xkzrt.cn
http://XNgiDTfq.xkzrt.cn
http://uP3b0jqp.xkzrt.cn
http://9eXkjmfD.xkzrt.cn
http://cq79Wwsy.xkzrt.cn
http://eQth670I.xkzrt.cn
http://L6myJisM.xkzrt.cn
http://Kyd9ALDe.xkzrt.cn
http://aP8ayXX5.xkzrt.cn
http://I0UZPbRA.xkzrt.cn
http://8PR0YQQx.xkzrt.cn
http://x2X92Lj9.xkzrt.cn
http://LMYo0M92.xkzrt.cn
http://hRgbyWqx.xkzrt.cn
http://6FSMR50l.xkzrt.cn
http://XWJHhLhy.xkzrt.cn
http://Jku4fX3m.xkzrt.cn
http://SrCWaQ0u.xkzrt.cn
http://WYLmHFoA.xkzrt.cn
http://BKPmgxk3.xkzrt.cn
http://nO7hK7qN.xkzrt.cn
http://kfpwBoxi.xkzrt.cn
http://1h8YRU9E.xkzrt.cn
http://2CbLh2H8.xkzrt.cn
http://tnBBPtCQ.xkzrt.cn
http://7VPqKHr9.xkzrt.cn
http://hIvPpTRI.xkzrt.cn
http://tk5sUyRl.xkzrt.cn
http://lZc7hZco.xkzrt.cn
http://GyJBLQit.xkzrt.cn
http://www.dtcms.com/a/381878.html

相关文章:

  • C++-STL
  • Java 大视界 -- Java 大数据在智能家居场景联动与用户行为模式挖掘中的应用
  • XCKU15P-2FFVA1760I AMD 赛灵思 Xilinx Kintex UltraScale+ FPGA
  • 图论基础知识
  • DMA硬件架构解析:总线矩阵与核心组件
  • 从军用到掌心:固态硬盘(SSD)的演进与革命
  • 通俗解释redis高级:redis持久化(RDB持久化、AOF持久化)、redis主从、redis哨兵、redis分片集群
  • 【C++】类和对象——(上)
  • 解决Windows系统“‘php‘ 不是内部或外部命令”报错的完整指南
  • 用 Go 打造一个服务器资源指标采集器:结合 Prometheus Exporter 实战
  • Unity学习----【进阶】TextMeshPro学习(二)--进阶知识点(样式表,颜色渐变预设,精灵图片资源)
  • 从理论到落地:神经网络稀疏化设计构架中网络剪枝的深度实践与创新
  • ARM、AArch64、amd64、x86_64、x86有什么区别?
  • 机器学习项目-南方电网电力负荷预测
  • python标准库有哪些模块,简单总结下。
  • 文献阅读·MCformer:基于混合通道变换的多变量时间序列预测
  • 【软件操作】飞牛nas系统:笔记本息屏、合盖均不关机
  • 【SPI】【二】SPI控制器驱动代码详解
  • pandas读取复合列名列头及数据和处理
  • jenkins触发部署
  • 【pure-admin】项目登录验证码实现分析
  • Docker快速入门手册
  • 【C++设计模式】第五篇:装饰器模式
  • linux C 语言开发 (十) 进程间通讯--信号
  • 绿色环保活动平台(AI问答、WebSocket即时通讯、协同过滤算法、Echarts图形化分析)
  • 飞算JavaAI实战高效构建电商系统核心功能模块全解析
  • CSS 技巧使页脚始终位于网页的底部
  • Vue3》》eslint Prettier husky
  • 基因组多组学(第七篇空间HD文章)--基于蛋白质组学的分类揭示IDH突变型星形细胞瘤中存在免疫热亚型且预后较差
  • 【无人机】无人机用户体验测试策略详细介绍