sqlalchemy2.0 新特性使用

news/2024/10/18 15:01:30/文章来源:https://www.cnblogs.com/shenh/p/18414272

一、前言

 sqlalchemy2.0及2.0+ 版本出的很多新特性,和之前的使用方法不太一样,并且删除了大部分已弃用的元素,将剩余的元素(主要是Query)降级为长期“遗留”状态。

 官方文档:点此链接

 

二、配置SQLALchemy

1、创建一个 plugin/plugin_sqlalchemy.py 文件,用来初始化 SQLalchemy 引擎

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import osSQLALCHEMY_DATABASE_URL = "mysql+pymysql://root:123456@localhost:3306/fastapi?charset=utf8mb4"
POOL_SIZE = 20
# SQLALCHEMY_DATABASE_URL = "postgresql://root:123456@postgresserver/db"engine = create_engine(SQLALCHEMY_DATABASE_URL,echo=True,  # echo 设为 True 会打印出实际执行的 sql,调试的时候更方便future=True,  # 使用 SQLAlchemy 2.0 API,向后兼容pool_size=POOL_SIZE, # 连接池的大小默认为 5 个,设置为 0 时表示连接无限制pool_recycle=3600, # 设置时间以限制数据库自动断开
)# SessionLocal该类的每个实例将是一个数据库会话。该类本身还不是数据库会话。
# 一旦我们创建了SessionLocal该类的实例,该实例将成为实际的数据库会话。
# 要创建SessionLocal类,请使用函数sessionmaker,sessionmaker是一个工厂函数,返回一个配置好的类
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()

 

2、在models层创建 baseModel.py 文件,定义一个基础数据表模型类。映射从一个基类开始,称为Base,它是通过对DeclarativeBase类进行简单的子类化创建的,baseModel继承Base类,之后的业务数据表模型都继承 baseModel 类。通过添加包含特殊类型注释的属性来声明表中的一部分列,该注释称为 Mapped。对于所有需要更具体自定义的基于列的属性,使用 mapped_column() 指令。

from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import Column,Integer,DATETIME
from datetime import datetimeclass Base(DeclarativeBase):passclass baseModel(Base):# 定义为抽象类__abstract__ = True# 默认字段id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True, comment="主键ID")create_user: Mapped[int] = mapped_column(Integer, default=0, comment="创建人")create_time: Mapped[datetime] = mapped_column(DATETIME, default=datetime.now, comment="创建时间")update_user: Mapped[int] = mapped_column(Integer, default=0, comment="更新人")update_time: Mapped[datetime] = mapped_column(DATETIME, default=datetime.now, comment="更新时间")is_delete: Mapped[int] = mapped_column(Integer, default=0, comment="删除标识:0-正常 1-已删除")

 

3、创建业务数据表模型 models/cms/user.py

from models.baseModel import baseModel
from sqlalchemy import String
from sqlalchemy.orm import Mapped,mapped_columnclass User(baseModel):__tablename__ = "user" # 数据库表名username: Mapped[str] = mapped_column(String(20), nullable=False, unique=True, comment="用户姓名")password: Mapped[str] = mapped_column(String(20), nullable=False, comment="密码")nickname: Mapped[str] = mapped_column(String(50),nullable=True, comment="昵称")email: Mapped[str] = mapped_column(String(50), nullable=True,  comment="电子邮箱")

 

4、models/__init__.py 自己封装一个方法,使用create_all() 创建数据库表。 

from plugin.pulgin_sqlalchamy import engine
from models.baseModel import Basedef register_database():# 预先创建数据表from .cms import userBase.metadata.create_all(bind=engine)

 

三、外键和relationship

通过 ForeignKey 设置子表user的group_id字段作为主表group的外键。relationship,这个类可以定义属性,定义一对多关系,以后在访问相关联的表的时候就直接可以通过属性访问的方式就可以访问得到了。

from models.baseModel import baseModel
from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.orm import relationship,Mapped,mapped_columnclass User(baseModel):__tablename__ = "user" # 数据库表名username: Mapped[str] = mapped_column(String(20), nullable=False, unique=True, comment="用户姓名")password: Mapped[str] = mapped_column(String(20), nullable=False, comment="密码")nickname: Mapped[str] = mapped_column(String(50),nullable=True, comment="昵称")email: Mapped[str] = mapped_column(String(50), nullable=True,  comment="电子邮箱")# # 设置外键约束group_id: Mapped[int] = mapped_column(Integer, ForeignKey('group.id',onupdate='RESTRICT'), nullable=False)# 声明式relationshipgroup: Mapped['Group'] = relationship(back_populates = 'user')class Group(baseModel):__tablename__ = "group" # 用户组name: Mapped[str] = mapped_column(String(20), nullable=False,unique=True, comment='用户组')info: Mapped[str] = mapped_column(String(20), nullable=True,comment='描述')level: Mapped[int] = mapped_column(Integer,nullable=True,comment='分组级别')user: Mapped[list['User']] = relationship(back_populates = 'group')

通过关联属性来访问相关联对象:

# 查询
# 通过user表查询到group的组名
db_user = db.scalars(select(User)).first()
groupName = db_user.group.name# 添加
db_group = Group(name = '研发中心')
# 方法一
User(username = 'lucy',password = '123456',group = db_group)
# 方法二:使用append方法
# db_user = User(username = 'lucy',password = '123456')
# db_group.user.append(db_user)
db.add(db_group)
db.commit()

 

 四、CRUD

1、和 1.x API 不同,2.0 API 中不再使用 query,而是使用 select 来查询数据。

from sqlalchemy import select
# 查询
res = db.execute(select(User).where(User.name == "spongebob"))
# 查询一条
# row = db.execute(select(User).order_by(User.id)).first()
# 使用scalars(),返回一个list[User实例]
# res = db.scalars(select(User).order_by(User.id)).all()
# 查询指定字段
# res = db.execute(select(User.name).order_by(User.id)).all()
for row in res:print(f'{row.id}{row.name}'# 从第5条记录开始(即跳过前4条),获取接下来的10条记录  
res = db.execute(select(User).offset(4).limit(10)).all() # 连表查询
select(User, Group).join(User.group).order_by(User.id, Group.id)
# 链表查询指定ON
select(User).join(Group, User.group_id == Group.id)
# 链表查询, relationship() 绑定的属性
select(User).join(Group, User.group)
# 查询指定字段
select(User.name, Group.name).join(User.group).order_by(User.id, group.id)# 给表起别名
from sqlalchemy.orm import aliased
user_cls = aliased(User, name="user_cls")
group_cls = aliased(Group, name="group_cls")
stmt = (select(user_cls, group_cls).join(user_cls.addresses.of_type(group_cls)).order_by(user_cls.id, group_cls.id))
row = db.execute(stmt).first()
print(f"{row.user_cls.name} {row.group_cls.name}")

 

2、INSERT数据库使用 insert() 替代 select(),批量添加数据:

from sqlalchemy import insert
# 批量add
db.execute(insert(User),[{"name": "spongebob", "nickname": "Spongebob Squarepants"},{"name": "sandy", "nickname": "Sandy Cheeks"},{"name": "patrick", "nickname": "Patrick Star"},{"name": "squidward", "nickname": "Squidward Tentacles"},{"name": "ehkrabs", "nickname": "Eugene H. Krabs"},],
)
db.commit()

 

3、UPDATE数据库使用 update() ,批量修改:

from sqlalchemy import update
# 批量update
db.execute(update(User),[{"id": 1, "nickname": "Spongebob Squarepants"},{"id": 3, "nickname": "Patrick Star"},{"id": 5, "nickname": "Eugene H. Krabs"},],
)# 加上where条件
from sqlalchemy import update
stmt = (update(User).where(User.name.in_(["squidward", "sandy"])).values(nickname="Name starts with S")
)
db.execute(stmt)# 同时更新两个scheeks,eugene
db.execute(update(Manager),[{"id": 1,"name": "scheeks","manager_name": "Sandy Cheeks, President",},{"id": 2,"name": "eugene","manager_name": "Eugene H. Krabs, VP Marketing",},],
)
db.commit()

 

4、DELETE数据库使用 delete() ,批量删除:

# 删除多个
from sqlalchemy import delete
stmt = delete(User).where(User.name.in_(["squidward", "sandy"]))
db.execute(stmt)
# 删除单个
from sqlalchemy import delete
db.execute(delete(User).where(User.id == 1))
db.execute(delete(Group).where(Group.id == 1))
db.commit()

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/816885.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【喜讯】全球电商大数据平台推出F类免费API接口服务!

好消息,全球电商大数据平台再次上线多个类别接口,首次推出F类免费API接口服务,为所有追求数据赋能、寻求创新突破的企业和个人,带来了前所未有的机遇。好消息,值此之际;全球电商大数据平台再次上线多个类别接口,首次推出F类免费API接口服务,为所有追求数据赋能、寻求创…

c# winform在线升级clickonce

说明:在线升级前提 1,一个可以访问在线的地址,2,发布前要在项目属性发布里配置好相关设置 一,可以在IIS上布署一个可以访问的地址 二,发布前配置

SQLSEVER 实现货币数字转中文汉字

SQLSEVER 实现数字转换成中文(货币) -- ============================================= -- Author: LearnerPing -- Create date: 2024/10/18 -- Description: Change Number to Chinese -- ============================================= Create FUNCTION GetNumberToChi…

javascript渲染OFD的库

目前使用javascript开发的OFD的渲染库主要有两个: ofd.js和liteofd,其中ofd.js开发比较早,liteofd是最近刚出现的js库。首先结论是ofd.js渲染效果没有liteofd好,因为ofd.js目前有一些效果没有支持,比如对字体没有比较好的解析和支持。 liteofd相对ofd.js效果更好,并且提供…

高等数学 6.1 定积分的元素法

在定积分的应用中,经常采用所谓的元素法。为了说明这种方法,先回顾一下曲边梯形的面积问题。 设 \(f(x)\) 在区间 \([a, b]\) 上连续且 \(f(x) \geqslant 0\) ,求以曲线 \(y = f(x)\) 为曲边、底为 \([a, b]\) 的曲边梯形的面积 \(A\) 。把这个面积 \(A\) 表示为定积分 \[A …

详解 JuiceFS 在多云架构下的数据同步与一致性

随着大模型流行,GPU 算力资源正变得日益稀缺,传统的“算力跟着存储跑”的策略需要转变为“存储跟着算力跑”。为了确保数据一致性和管理的便捷性,企业通常在特定地区的公有云上选择对象存储作为所有模型数据的集中存储点。当进行计算任务调度时,往往需要人工介入,手动进行…

Renderer

Renderer 模块 Renderer 模块的设置决定了粒子的图像或网格如何被其他粒子变换、着色和过度绘制。 粒子系统Unity中创建粒子系统渲染器模块视图 细节 使用渲染模式在多种 2D Billboard 图形模式和网格模式之间进行选择。当粒子代表固体游戏对象(例如岩石)时,3D 网格赋予粒子…

WDT

参考:https://zhuanlan.zhihu.com/p/711237133 模式 1.WDGIF_FAST_MODE:mode1 2.WDGIF_OFF_MODE:mode2 3.WDGIF_SLOW_MODE:mode0 默认初始化为WDGIF_SLOW_MODE,等待初始化完成后切换成WDGIF_FAST_MODEWDGIF_FAST_MODE设置:问题:反复重启WDGIF_SLOW_MODE模式下,初始化过程…

轻松上手-图片压缩秘籍

作者:狼哥 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁…

记上报信息格式异常问题的解决

本文记述遇到字符串中包含无效字符时的格式化异常问题的全过程。本文记述解决上报信息格式异常问题的全过程。 问题描述 生产环境监控上报无法解析终端信息,通过日志发现是PCN字段前面缺失#号,导致解析程序解析失败。正常情况下,应该展示如下内容:HD1234#PCN1234发生错误情…

云存储图片生成缩略图开发

作者:狼哥 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁…

PHP简介与开发环境搭建

PHP简介与开发环境搭建 一、PHP简介 PHP,全称PHP: Hypertext Preprocessor(超文本预处理器),是一种广泛使用的开源服务器端脚本语言,尤其适合Web开发。PHP由Rasmus Lerdorf在1994年创建,最初是为了维护个人网页而制作的简单程序,后来逐渐发展成为功能强大的脚本语言。PH…