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

SqlAlchemy使用教程(五) ORM API 编程入门

在这里插入图片描述

  • SqlAlchemy使用教程(一) 原理与环境搭建
  • SqlAlchemy使用教程(二) 入门示例及编程步骤
  • SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解
  • SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用
  • SqlAlchemy使用教程(五) ORM API 编程入门

前一章用SQL表达式(SQL Express)语法操作数据库时,仍然侧重于从Core API的角度来看 SQL表达式语言,主要目的是通过封装的SQL表达式来实现跨不同数据库目的。

本章主要介绍ORM API 基础知识、实现ORM CRUD 基础操作。我尽可能使用简洁的语言,配合实例代码,帮助你尽快上手。下一章将深入学习ORM API的主要方法、使用方式,以及较复杂需求的编程实现。

1、ORM 原理

在第1章介绍过ORM原理时。 Python类对象通过ORM与数据库Table进行映射,通过Python类对象的方式来操作数据库。开发人员无须再使用各类数据库的接口API,以及SQL语法。
在这里插入图片描述

注: ORM的理想很丰满,现实却是这样的:用好ORM还是需要扎实的SQL基础才能用好。

ORM如何实现从Python对象到数据库的映射呢?

  1. 这种映射结构可分为如下几层
  2. Python Table类: 将 Database 的表结构 => 表示为 Python Metadata, 数据库字段 => Python Table类的属性(Column对象)
  3. Python Table 对象:数据的每行记录相当于1个Python类的实例对象(object),多行用 `object 列表` 表示。
  4. 数据库操作的ORM实现
    • 插入1行数据,就相当于: 新建1个Python类实例对象,通过ORM插入数据库
    • 通过ORM查询数据库,返回值为Python对象列表

2、ORM基础编程步骤

2.1 ORM API的使用步骤:

预备知识:

metadata:
上一章已详细介绍过,用于保存表结构, 通常1个应用定义1个全局metadata对象, 集中保存表结构。

declarative Table 声明式Table类
将数据库的表、字段,定义成Python类与属性的结构,这种结构称为声明式映射(Declarative Mapping)。Sqlalchemy2以后。table 类必须继承自 DeclarativeBase。

ORM API的使用流程:
(1)定义1个DeclarativeBase子类,做为Python table类的父类
(2)定义table类,映射到1个数据库表
(3)通过engine在数据库中实际创建表。 由Base.metadata向engine 发关create table DDL的事件.
(4)创建session对象,连接到engine,用于管理后续数据库操作。
(5)使用SQL Express Language语法的select, insert, update, delete等方法来执行数据库的增删改查操作。

说明:此处提到的 table 类,是为了描述方便,此类用于映射数据库表,不是上一节提到的sqlalchemy.Table 内置类。

2.2 声明式映射语法定义Table类与Column类

1)申明式定义table 类

继承自DeclarativeBase, column 字段定义遵照mapping 语法

定义1个Base做为Table类的基类

from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):pass

注:Base对象包含metadfata. registry 属性

Base.metadata
Base.registry

设置数据库表名
__tablename__ = "user_account" , 设置为db table 名

定义column属性,
name: Mapped[str] = mapped_column(String(30))
等号左边使用type notation注明Python类型,右边用mapped_column()给出最匹配的Database字段类型
这是SqlAlchemy2.0推荐的方式,别嫌麻烦,这样做可以大大减少数据库迁移时出错的概率,

下面是1个用声明式映射方式定义的Person 类。

from sqlalchemy.orm import DeclarativeBase, Session
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import String, Integerclass Base(DeclarativeBase):passclass Person(Base):__tablename__ = 'person'id: Mapped[int] = mapped_column(primary_key=True)name: Mapped[str] = mapped_column(String(30))age: Mapped[int] = mapped_column(Integer)def __init__(self, name: str, age: int):self.name = nameself.age = agedef __repr__(self):return f"Person({self.name}, {self.age})"

说明:
上述模型类,除将用属性映射到数据库字段外,与普通类定义一样,也提供了对象初始化方法__init__(),以及__repr__()魔法方法。 还可以添加其它的方法,如属性的校验方法等。

2)通过engine对象在数据库中创建表

创建数据库连接引擎对象

engine = create_engine("mysql+mysqlconnector://root:12345678@localhost:3306/testdb")
# 请用你的mysql用户名及密码替换root:12345678

将DDL语句映射到数据库表,如果数据库表不存在,则创建该表

Base.metadata.create_all(engine)

2.3 向数据库插入数据

我们现在可以在数据库中插入数据了。通过创建类的实例来实现这一点. 还要使用一个名为Session的对象将它们传递到数据库,该对象利用Engine与数据库进行交互。使用Se木本油料Session.add(obj)添加1个对象(数据记录行),或使用Session.add_all()方法一次添加多个对象,而Session.commit()方法将用于保存对数据库的变更。

session = Session(engine)
# 创建Person实例对象
p1 = Person("刘备", 40)
p2 = Person("关羽", 38)
p3 = Person("张飞", 35)
# 将Person实例对象添加到session
session.add(p1)
session.add(p2)
session.add(p3)
session.commit()  # 提交事务到数据库

建议通过上下文管理器使用Session,即使用Python with语句。

2.4简单SELECT查询

对于数据库中的某些行,以下是发出SELECT语句以加载某些对象的最简单形式。要创建SELECT语句,
1)使用SELECT() 函数创建一个新的SELECT对象.
2) 使用Session调用该对象。在查询ORM对象时,通常有用的方法是Session.scalars()方法,它将返回一个ScalarResult对象,该对象将遍历我们选择的ORM对象:

stmt = select(Person).where(Person.name == "刘备")
results = session.scalars(stmt)
print(results.all())

Output:

[Person(刘备, 40)]

返回值 results对象为ScalarResult类实例,成员方法 all()以列表方式获取查询结果, 是1个对象列表,也很符合OOP的规范。

ScalarResult对象还提供了first(), fetchone(), fetchmany(), fetchall()等方法,习惯于DBAPI编程的同样都很熟悉。

ScalarResult对象也是可迭代的,用for 循环遍历读取结果

stmt = select(Person).where(Person.name.in_(["刘备", "关羽"]))
results = session.scalars(stmt)
for p in results:
print(p)

Output:

Person(刘备, 40)
Person(关羽, 38)

查询全部数据

results = session.scalars(select(Person).order_by(Person.age))

多条件查询

Where()方法不支持 and, or逻辑运算符,但支持where()方法的链式调用来实现多条件查询。

stmt = select(Person).where(Person.age > 35).where(Person.age < 50)
results = session.scalars(stmt)
print(results.all())

2.4 更新数据

更新数据时,先以对象的方式读取到1条数据后,更新该对象的属性,然后通过session提交事件,即自动将更新数据库相应记录。
例如。我们先在Person表中插入1条name=”张辽”的数据

p4 = Person("张辽", 36)
session.add(p4)
session.commit()  # 提交事务到数据库

然后获取该记录对象,将name属性改为”赵云”,提交更新。

stmt = select(Person).where(Person.name == "张辽")
person = session.scalars(stmt).first()
person.name = "赵云"
person.age = 32
session.commit()
results = session.scalars(select(Person).order_by(Person.age))
print(results.all())

Output

[Person(赵云, 32), Person(张飞, 35), Person(关羽, 38), Person(刘备, 40)]

2.5 删除数据

删除数据,也就是用session.delete()方法向engine传递1个对象。如果该对象不存在,则会抛出异常,如果该对象存在,则删除。

p5 = Person("曹操", 50)
try:session.delete(p5)
except Exception as e:print("数据库中不存在该记录")
p6 = session.scalars(select(Person).where(Person.name == "赵云")).first()
session.delete(p6)
session.commit()
results = session.scalars(select(Person).order_by(Person.age))
print(results.all())

Output:
数据库中不存在该记录

[Person(张飞, 35), Person(关羽, 38), Person(刘备, 40)]

3. 本章小结

ORM API编程的基本流程为:
1)用声明式映射方式,定义Python Table类,其父类必须是DeclarativeBase
2)Table类的属性映射到数据库字段,左边用 maped()注明Python类型,右边用mapped_column()申明对应的数据库字段类型。
3)用Base.metadata.emit()方法将DDL语句发送到数据库创建表。
4)创建Session对象,做为ORM 至 Database的管理器。
5)通过实例对象完成数据库的添加、修改、删除操作
6)通过select()查询数据, 并且提供了where(), order_by()等支持条件查询,排序等。

相关文章:

  • MetaGPT-打卡-day2,MetaGPT框架组件学习
  • 网络安全概述
  • 旧路由重置新路由设置新路由设置教程|适用于自动获取IP模式
  • C#调用Newtonsoft.Json将bool序列化为int
  • HttpServletRequest getHeader、getHeaders、getIntHeader、getDateHeader区别
  • EMI兼容测试方案——匹配不同测试标准,准确高效!
  • STM32-串口解析框架
  • 使用Nginx和Fancyindex组合搭建文件下载站点详细教程
  • 【Linux】Shell 命令以及运行原理
  • 【Linux】进程退出和进程等待
  • 单点安装3.6.23_ubuntu18.04
  • 前端构建工具对比 webpack、vite、esbuild等
  • 广和通AI解决方案“智”赋室外机器人迈向新天地!
  • 使用Python自动化操作手机,自动执行常见任务,例如滑动手势、呼叫、发送短信等等
  • 【SpringCloud Alibaba】 介绍及微服务模块搭建
  • 【node学习】协程
  • Codepen 每日精选(2018-3-25)
  • JAVA SE 6 GC调优笔记
  • magento2项目上线注意事项
  • Next.js之基础概念(二)
  • python大佬养成计划----difflib模块
  • scrapy学习之路4(itemloder的使用)
  • windows下mongoDB的环境配置
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 从tcpdump抓包看TCP/IP协议
  • 大快搜索数据爬虫技术实例安装教学篇
  • 翻译--Thinking in React
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 后端_MYSQL
  • 深度解析利用ES6进行Promise封装总结
  • 与 ConTeXt MkIV 官方文档的接驳
  • # 计算机视觉入门
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • %@ page import=%的用法
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (c语言)strcpy函数用法
  • (solr系列:一)使用tomcat部署solr服务
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (转)Sql Server 保留几位小数的两种做法
  • .net 发送邮件
  • @RequestMapping 的作用是什么?
  • []常用AT命令解释()
  • [20140403]查询是否产生日志
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [bzoj1038][ZJOI2008]瞭望塔
  • [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
  • [C++]STL之map
  • [C++随笔录] 红黑树
  • [Effective C++读书笔记]0012_复制对象时勿忘其每一部分
  • [HackMyVM]靶场 Quick3
  • [hdu 3746] Cyclic Nacklace [kmp]
  • [hive] 窗口函数 ROW_NUMBER()
  • [IDF]啥?
  • [IE编程] 了解Urlmon.dll和Wininet.dll