使用 SQLAlchemy 強(qiáng)大的 ORM 處理應(yīng)用程序的數(shù)據(jù)層。純粹用 Python 定義數(shù)據(jù)模型、添加/刪除記錄以及執(zhí)行查詢(xún)。
使用 ORM 作為數(shù)據(jù)層是一個(gè)與面向?qū)ο缶幊瘫旧硪粯庸爬系母拍?。通過(guò)抽象 SQL 概念,開(kāi)發(fā)人員可以通過(guò)修改對(duì)象而不是查詢(xún)來(lái)避免可怕的“上下文切換”。ORM 不僅僅是過(guò)度熱衷的 OOP 時(shí)代慢慢衰落的產(chǎn)物;它也是 OOP 時(shí)代的產(chǎn)物。它們通過(guò)確保應(yīng)用程序端的數(shù)據(jù)完整性來(lái)保證一定程度的持久性,從而最大限度地減少災(zāi)難性 SQL 查詢(xún)的可能性。
ORM 允許開(kāi)發(fā)人員通過(guò)修改代碼中的對(duì)象(數(shù)據(jù)類(lèi))來(lái)處理數(shù)據(jù),而不是對(duì)數(shù)據(jù)庫(kù)執(zhí)行 SQL 查詢(xún)。此工作流程對(duì)于定期驗(yàn)證和修改數(shù)據(jù)(例如驗(yàn)證用戶(hù)、修改配置文件、發(fā)布內(nèi)容等)的面向用戶(hù)的應(yīng)用程序是有好處的。ORM 的亮點(diǎn)在于提供了一個(gè)用于處理頻繁且可預(yù)測(cè)的操作的接口;這對(duì)于應(yīng)用程序開(kāi)發(fā)至關(guān)重要,但對(duì)于涉及數(shù)據(jù)分析的任何事情來(lái)說(shuō)肯定是一種負(fù)擔(dān)。
創(chuàng)建模型
數(shù)據(jù)模型是代表數(shù)據(jù)庫(kù)中 SQL 表的 Python 類(lèi),其中模型的屬性轉(zhuǎn)換為表中的列。
使用 ORM 時(shí),創(chuàng)建模型實(shí)例會(huì)轉(zhuǎn)化為在 SQL表中創(chuàng)建行。當(dāng)然,這意味著我們需要先定義模型,然后才能編寫(xiě)任何有意義的業(yè)務(wù)邏輯。
我們通過(guò)定義 Python 類(lèi)來(lái)創(chuàng)建模型,這些類(lèi)擴(kuò)展了 SQLAlchemy 中稱(chēng)為declarative_base(). 我們這樣定義模型“基礎(chǔ)”對(duì)象:
"""SQLAlchemy 數(shù)據(jù)模型。""" from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
現(xiàn)在我們可以擴(kuò)展Base以創(chuàng)建我們的第一個(gè)模型。按照傳統(tǒng),我們的第一個(gè)模型將是一個(gè)代表用戶(hù)帳戶(hù)的模型,恰當(dāng)?shù)孛麨閁ser。我們將從簡(jiǎn)單開(kāi)始:
"""SQLAlchemy 數(shù)據(jù)模型。""" from sqlalchemy import Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.types import Integer, Text, String Base = declarative_base() class User(Base): """User account.""" __tablename__ = "user" id = Column(Integer, primary_key=True, autoincrement="auto") username = Column(String(255), unique=True, nullable=False) password = Column(Text, nullable=False)
雖然上面的 Python 類(lèi)可能是準(zhǔn)系統(tǒng),但它是一個(gè)完全有效的數(shù)據(jù)模型,它將生成一個(gè)包含三列(每個(gè)屬性一列)的表:id、username和password。這些屬性中的每一個(gè)都具有類(lèi)型Column(),這是 SQLAlchemy 獨(dú)有的數(shù)據(jù)結(jié)構(gòu)(因此我們包含from sqlalchemy import Column)。
我們還導(dǎo)入了三個(gè) SQLAlchemy“類(lèi)型”,我們看到它們被傳遞到每個(gè)Column. 每種類(lèi)型對(duì)應(yīng)一個(gè) SQL 數(shù)據(jù)類(lèi)型。因此,我們的 SQL 表列的數(shù)據(jù)類(lèi)型將分別是integer、varchar(255)和text。
Columns 還可以接受鍵或列約束等可選參數(shù):
Primary_key:將列指定為表的“主鍵”,這是強(qiáng)烈推薦的做法,它充當(dāng)唯一標(biāo)識(shí)符以及 SQL 搜索的索引。
自動(dòng)增量primary_key:僅與類(lèi)型為 且具有類(lèi)型的列相關(guān)Integer。我們創(chuàng)建的每個(gè)用戶(hù)都會(huì)自動(dòng)分配一個(gè) id,其中第一個(gè)用戶(hù)的 id 為1,后續(xù)用戶(hù)的 id 會(huì)相應(yīng)增加。
unique:放置一個(gè)約束,其中沒(méi)有兩個(gè)記錄/行共享給定列的相同值(我們不希望兩個(gè)用戶(hù)具有相同的用戶(hù)名)。
nullable:當(dāng)設(shè)置為 時(shí)True,會(huì)添加一個(gè)約束,即該列是必需的,除非提供值,否則不會(huì)創(chuàng)建任何行。
key:在給定列上放置輔助鍵,通常與另一個(gè)約束(例如“索引”)一起使用。
index:指定列的值可以以非任意方式排序,以提高查詢(xún)性能
server_default:如果未顯式傳遞值,則分配默認(rèn)值。
在我們的示例中,我們?cè)O(shè)置可選屬性__tablename__來(lái)顯式指定應(yīng)命名哪個(gè)模型的相應(yīng) SQL 表。如果不存在,SQL 將使用類(lèi)的名稱(chēng)來(lái)創(chuàng)建表。
有了所有這些知識(shí),我們可以繼續(xù)構(gòu)建我們的模型:
... from sqlalchemy.types import Integer, Text, String, DateTime from sqlalchemy.sql import func class User(Base): """User account.""" __tablename__ = "user" id = Column(Integer, primary_key=True, autoincrement="auto") username = Column(String(255), unique=True, nullable=False) password = Column(Text, nullable=False) email = Column(String(255), unique=True, nullable=False) first_name = Column(String(255)) last_name = Column(String(255)) bio = Column(Text) avatar_url = Column(Text) created_at = Column(DateTime, server_default=func.now()) updated_at = Column(DateTime, server_default=func.now()) def __repr__(self): return f"<User {self.username}>"
現(xiàn)在這是一個(gè)模型!我們?cè)谀P椭刑砑恿艘恍傩?,每個(gè)屬性都是不言自明的。和列演示了如何使用 SQLAlchemycreated_at函數(shù)updated_at自動(dòng)分配這些值。
最佳實(shí)踐是設(shè)置__repr__數(shù)據(jù)模型(以及一般的 Python 類(lèi))的值,以便記錄或調(diào)試我們的類(lèi)實(shí)例。返回的值是我們?cè)诘膶?shí)例__repr__時(shí)看到的值。如果您曾經(jīng)不得不使用Javascript 進(jìn)行處理,那么您已經(jīng)熟悉了調(diào)試對(duì)象的值卻得不到任何有用的回報(bào)是多么令人討厭。print()User[object Object]
我們的模型看起來(lái)不錯(cuò),所以讓我們用它創(chuàng)建一個(gè) SQL 表。create_tables()我們通過(guò)調(diào)用創(chuàng)建模型后調(diào)用的方法來(lái)做到這一點(diǎn):
從擴(kuò)展的類(lèi)創(chuàng)建 SQL 表Base:
Base.metadata.create_all(engine)
一旦運(yùn)行,SQLAlchemy 就會(huì)處理數(shù)據(jù)庫(kù)端的所有事情,以創(chuàng)建與我們的模型匹配的表。如果您好奇,這就是我們的User模型輸出的內(nèi)容:
用于根據(jù)我們的數(shù)據(jù)模型創(chuàng)建表的 SQL 語(yǔ)句:
CREATE TABLE "user" ( "id" int NOT NULL AUTO_INCREMENT, "username" varchar(255) NOT NULL, "password" text NOT NULL, "email" varchar(255) NOT NULL, "first_name" varchar(255) DEFAULT NULL, "last_name" varchar(255) DEFAULT NULL, "bio" text, "avatar_url" text, "last_seen" datetime DEFAULT NULL, "created_at" datetime DEFAULT CURRENT_TIMESTAMP, "updated_at" datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY ("id"), UNIQUE KEY "username" ("username"), UNIQUE KEY "email" ("email"));
創(chuàng)建會(huì)話
會(huì)話是一種持久的數(shù)據(jù)庫(kù)連接,可讓我們輕松添加、刪除、更改甚至撤消更改。我們將使用User剛剛創(chuàng)建的模型通過(guò)數(shù)據(jù)庫(kù)會(huì)話創(chuàng)建新用戶(hù)。
會(huì)話是通過(guò)將它們綁定到 SQLAlchemy 引擎來(lái)創(chuàng)建的,我們?cè)诒鞠盗械牡?1 部分中介紹了該引擎。創(chuàng)建引擎后,我們所需要做的就是使用 SQLAlchemysessionmaker定義會(huì)話并將其綁定到我們的引擎:
"""數(shù)據(jù)庫(kù)引擎和會(huì)話創(chuàng)建。""" from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine( 'mysql+pymysql://user:password@host:3600/database', echo=True ) Session = sessionmaker(bind=engine) session = Session()
這就是所需要的一切!我們將session與我們的模型一起使用User來(lái)創(chuàng)建一些用戶(hù)。
使用模型和會(huì)話創(chuàng)建記錄
定義模型并創(chuàng)建會(huì)話后,我們可以純粹使用 Python 添加和修改數(shù)據(jù)。SQLAlchemy 將此稱(chēng)為基于函數(shù)的查詢(xún)構(gòu)造。讓我們看看從我們的類(lèi)中創(chuàng)建一個(gè)新用戶(hù)需要做什么User:
from models import User from database import session user = User( username="admin", password="Please don't set passwords like this", email="admin@example.com", first_name="Todd", last_name="Birchard", bio="I write tutorials on the internet.", avatar_url="https://example.com/avatar.jpg" ) session.add(user) # 添加用戶(hù) session.commit() # 提交更改
User通過(guò)創(chuàng)建并保存為變量的實(shí)例new_user,在數(shù)據(jù)庫(kù)中創(chuàng)建該用戶(hù)所需的只是對(duì)會(huì)話的兩次調(diào)用:add()將項(xiàng)目排隊(duì)等待創(chuàng)建,然后commit()保存更改。我們現(xiàn)在應(yīng)該在數(shù)據(jù)庫(kù)的用戶(hù)表中看到一行!
使用session方法很簡(jiǎn)單,只需四種簡(jiǎn)單的方法:
session.add():我們可以傳遞數(shù)據(jù)模型的實(shí)例來(lái)add()快速創(chuàng)建要添加到數(shù)據(jù)庫(kù)中的新記錄。
session.delete():與上面一樣,delete()接受數(shù)據(jù)模型的實(shí)例。如果該記錄存在于我們的數(shù)據(jù)庫(kù)中,它將被暫存以進(jìn)行刪除。
session.commit():在顯式提交之前,不會(huì)保存會(huì)話中所做的更改。
session.close():與 SQLAlchemy 引擎不同,會(huì)話是在顯式關(guān)閉之前保持打開(kāi)狀態(tài)的連接。
刪除記錄的語(yǔ)法與創(chuàng)建記錄的語(yǔ)法非常相似。有了user變量,刪除我們創(chuàng)建的用戶(hù)就像下面一樣簡(jiǎn)單:
session.delete(new_user) session.commit()
new_user就像魔術(shù)一樣,我們通過(guò)簡(jiǎn)單地傳遞到刪除方法來(lái)刪除與我們之前創(chuàng)建的記錄相匹配的記錄。不要只相信我的話:這個(gè)過(guò)程中最令人滿(mǎn)意的部分就是親眼看到它發(fā)生!嘗試使用您選擇的 GUI 連接到數(shù)據(jù)庫(kù),并觀察您運(yùn)行的每行代碼創(chuàng)建和刪除的記錄。文章來(lái)源:http://www.zghlxwxcb.cn/article/579.html
關(guān)鍵詞:SQLAlchemy,ORM數(shù)據(jù)模型,SQL表,Python類(lèi),數(shù)據(jù)模型文章來(lái)源地址http://www.zghlxwxcb.cn/article/579.html
到此這篇關(guān)于使用SQLAlchemy實(shí)施ORM數(shù)據(jù)模型 - 優(yōu)化數(shù)據(jù)庫(kù)操作的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!