- SqlAlchemy使用教程(一) 原理與環(huán)境搭建
- SqlAlchemy使用教程(二) 入門示例及編程步驟
- SqlAlchemy使用教程(三) CoreAPI訪問與操作數(shù)據(jù)庫詳解
- SqlAlchemy使用教程(四) MetaData 與 SQL Express Language 的使用
- SqlAlchemy使用教程(五) ORM API 編程入門
前一章用SQL表達式(SQL Express)語法操作數(shù)據(jù)庫時,仍然側(cè)重于從Core API的角度來看 SQL表達式語言,主要目的是通過封裝的SQL表達式來實現(xiàn)跨不同數(shù)據(jù)庫目的。
本章主要介紹ORM API 基礎(chǔ)知識、實現(xiàn)ORM CRUD 基礎(chǔ)操作。我盡可能使用簡潔的語言,配合實例代碼,幫助你盡快上手。下一章將深入學習ORM API的主要方法、使用方式,以及較復(fù)雜需求的編程實現(xiàn)。
1、ORM 原理
在第1章介紹過ORM原理時。 Python類對象通過ORM與數(shù)據(jù)庫Table進行映射,通過Python類對象的方式來操作數(shù)據(jù)庫。開發(fā)人員無須再使用各類數(shù)據(jù)庫的接口API,以及SQL語法。
注: ORM的理想很豐滿,現(xiàn)實卻是這樣的:用好ORM還是需要扎實的SQL基礎(chǔ)才能用好。
ORM如何實現(xiàn)從Python對象到數(shù)據(jù)庫的映射呢?
- 這種映射結(jié)構(gòu)可分為如下幾層
- Python Table類: 將 Database 的表結(jié)構(gòu) => 表示為 Python Metadata, 數(shù)據(jù)庫字段 => Python Table類的屬性(Column對象)
- Python Table 對象:數(shù)據(jù)的每行記錄相當于1個Python類的實例對象(object),多行用 `object 列表` 表示。
- 數(shù)據(jù)庫操作的ORM實現(xiàn)
- 插入1行數(shù)據(jù),就相當于: 新建1個Python類實例對象,通過ORM插入數(shù)據(jù)庫
- 通過ORM查詢數(shù)據(jù)庫,返回值為Python對象列表
2、ORM基礎(chǔ)編程步驟
2.1 ORM API的使用步驟:
預(yù)備知識:
metadata:
上一章已詳細介紹過,用于保存表結(jié)構(gòu), 通常1個應(yīng)用定義1個全局metadata對象, 集中保存表結(jié)構(gòu)。
declarative Table 聲明式Table類
將數(shù)據(jù)庫的表、字段,定義成Python類與屬性的結(jié)構(gòu),這種結(jié)構(gòu)稱為聲明式映射(Declarative Mapping)。Sqlalchemy2以后。table 類必須繼承自 DeclarativeBase。
ORM API的使用流程:
(1)定義1個DeclarativeBase子類,做為Python table類的父類
(2)定義映射table類,映射到1個數(shù)據(jù)庫表
(3)通過engine在數(shù)據(jù)庫中實際創(chuàng)建表。 由Base.metadata向engine 發(fā)關(guān)create table DDL的事件.
(4) 創(chuàng)建Session對象,連接到engine,用于管理后續(xù)數(shù)據(jù)庫操作。
(5) ORM對數(shù)據(jù)的增刪改查操作,與Core API 有明顯不同。 ORM的添加、修改、刪除操作是通過Session來操作映射Table類的對象來完成。ORM查詢使用的 select()方法也對 SQL表達式做了進一步封裝,輸入是以映射Table對象,而非metadata 的table類。
說明:此處提到的 table 類,是為了描述方便,此類用于映射數(shù)據(jù)庫表,不是上一節(jié)提到的sqlalchemy.Table 內(nèi)置類。
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
設(shè)置數(shù)據(jù)庫表名__tablename__ = "user_account"
, 設(shè)置為db table 名
定義column屬性,name: Mapped[str] = mapped_column(String(30))
等號左邊使用type notation注明Python類型,右邊用mapped_column()給出最匹配的Database字段類型
這是SqlAlchemy2.0推薦的方式,別嫌麻煩,這樣做可以大大減少數(shù)據(jù)庫遷移時出錯的概率,
下面是1個用聲明式映射方式定義的Person 類。
from sqlalchemy.orm import DeclarativeBase, Session
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import String, Integer
class Base(DeclarativeBase):
pass
class 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 = name
self.age = age
def __repr__(self):
return f"Person({self.name}, {self.age})"
說明:
上述模型類,除將用屬性映射到數(shù)據(jù)庫字段外,與普通類定義一樣,也提供了對象初始化方法__init__(),以及__repr__()魔法方法。 還可以添加其它的方法,如屬性的校驗方法等。
2)通過engine對象在數(shù)據(jù)庫中創(chuàng)建表
創(chuàng)建數(shù)據(jù)庫連接引擎對象
engine = create_engine(
"mysql+mysqlconnector://root:12345678@localhost:3306/testdb")
# 請用你的mysql用戶名及密碼替換root:12345678
將DDL語句映射到數(shù)據(jù)庫表,如果數(shù)據(jù)庫表不存在,則創(chuàng)建該表
Base.metadata.create_all(engine)
2.3 向數(shù)據(jù)庫插入數(shù)據(jù)
我們現(xiàn)在可以在數(shù)據(jù)庫中插入數(shù)據(jù)了。通過創(chuàng)建類的實例來實現(xiàn)這一點. 還要使用一個名為Session的對象將它們傳遞到數(shù)據(jù)庫,該對象利用Engine與數(shù)據(jù)庫進行交互。使用Se木本油料Session.add(obj)添加1個對象(數(shù)據(jù)記錄行),或使用Session.add_all()方法一次添加多個對象,而Session.commit()方法將用于保存對數(shù)據(jù)庫的變更。
session = Session(engine)
# 創(chuàng)建Person實例對象
p1 = Person("劉備", 40)
p2 = Person("關(guān)羽", 38)
p3 = Person("張飛", 35)
# 將Person實例對象添加到session
session.add(p1)
session.add(p2)
session.add(p3)
session.commit() # 提交事務(wù)到數(shù)據(jù)庫
建議通過上下文管理器使用Session,即使用Python with語句。
2.4簡單SELECT查詢
對于數(shù)據(jù)庫中的某些行,以下是發(fā)出SELECT語句以加載某些對象的最簡單形式。要創(chuàng)建SELECT語句,
1)使用SELECT() 函數(shù)創(chuàng)建一個新的SELECT對象.
2) 使用Session調(diào)用該對象。執(zhí)行ORM查詢時,最常用方法是Session.scalars()方法,它將返回一個ScalarResult對象,該對象將遍歷我們選擇的ORM對象. (另1個執(zhí)行方法 Session.execute() 在后面章節(jié)也會介紹)
stmt = select(Person).where(Person.name == "劉備")
results = session.scalars(stmt)
print(results.all())
Output:
[Person(劉備, 40)]
返回值 results對象為ScalarResult類實例, all()以對象列表方式返回查詢結(jié)果, 每個元素是1個映射table類對象 ,每個對象的各個屬性,相對應(yīng)于數(shù)據(jù)庫表的字段值。
ScalarResult對象還提供了first(), fetchone(), fetchmany(), fetchall()等方法,習慣于DBAPI編程的同樣都很熟悉。
ScalarResult對象也是可迭代的,用for 循環(huán)遍歷讀取結(jié)果
stmt = select(Person).where(Person.name.in_(["劉備", "關(guān)羽"]))
results = session.scalars(stmt)
for p in results:
print(p)
Output:
Person(劉備, 40)
Person(關(guān)羽, 38)
查詢?nèi)繑?shù)據(jù)
results = session.scalars(select(Person).order_by(Person.age))
多條件查詢
Where()方法不支持 and, or邏輯運算符,但支持where()方法的鏈式調(diào)用來實現(xiàn)多條件查詢。
stmt = select(Person).where(Person.age > 35).where(Person.age < 50)
results = session.scalars(stmt)
print(results.all())
2.4 更新數(shù)據(jù)
更新數(shù)據(jù)時,先以對象的方式讀取到1條數(shù)據(jù)后,更新該對象的屬性,然后通過session提交事件,即自動將更新數(shù)據(jù)庫相應(yīng)記錄。
例如。我們先在Person表中插入1條name=”張遼”的數(shù)據(jù)
p4 = Person("張遼", 36)
session.add(p4)
session.commit() # 提交事務(wù)到數(shù)據(jù)庫
然后獲取該記錄對象,將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(關(guān)羽, 38), Person(劉備, 40)]
2.5 刪除數(shù)據(jù)
刪除數(shù)據(jù),也就是用session.delete()方法向engine傳遞1個對象。如果該對象不存在,則會拋出異常,如果該對象存在,則刪除。
p5 = Person("曹操", 50)
try:
session.delete(p5)
except Exception as e:
print("數(shù)據(jù)庫中不存在該記錄")
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:
數(shù)據(jù)庫中不存在該記錄文章來源:http://www.zghlxwxcb.cn/news/detail-816883.html
[Person(張飛, 35), Person(關(guān)羽, 38), Person(劉備, 40)]
3. 本章小結(jié)
ORM API編程的基本流程為:
1)用聲明式映射方式,定義Python Table類,其父類必須是DeclarativeBase
2)Table類的屬性映射到數(shù)據(jù)庫字段,左邊用 maped()注明Python類型,右邊用mapped_column()申明對應(yīng)的數(shù)據(jù)庫字段類型。
3)用Base.metadata.emit()方法將DDL語句發(fā)送到數(shù)據(jù)庫創(chuàng)建表。
4)創(chuàng)建Session對象,做為ORM 至 Database的管理器。
5)通過實例對象完成數(shù)據(jù)庫的添加、修改、刪除操作
6)通過select()查詢數(shù)據(jù), 并且提供了where(), order_by()等支持條件查詢,排序等。文章來源地址http://www.zghlxwxcb.cn/news/detail-816883.html
到了這里,關(guān)于SqlAlchemy使用教程(五) ORM API 編程入門的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!