Python SQLalchemy的學(xué)習(xí)與使用

<time datetime="2019-04-19T12:31:08.000Z" data-reader-unique-id="339" class="date" style="margin: 0px; max-width: 100%; font-size: 1em !important; font-weight: normal !important; font-style: normal !important; display: inline !important;">2019.04.19 20:31:08</time>

SQLAlchemy是python中最著名的ORM(Object Relationship Mapping)框架了刽肠。

前言:什么是ORM咖楣?

ORM操作是所有完整軟件中后端處理最重要的一部分罗售,主要完成了后端程序和數(shù)據(jù)庫之間的數(shù)據(jù)同步和持久化的操作震庭。

數(shù)據(jù)庫表示一個二維表征炼,包含多行多列间聊。把一個表的內(nèi)容用python的數(shù)據(jù)結(jié)構(gòu)表示出來的話笤虫,可以用一個list表示多行,list的每一個元素是tuple直撤,表示一行記錄非竿,比如,包含id和name的user表:

[圖片上傳失敗...(image-82751b-1586172584834)]

Python的DB-API返回的數(shù)據(jù)結(jié)構(gòu)就是像上面這樣表示的谋竖。但是用tuple表示一行很難看出表的結(jié)構(gòu)汽馋,如果把一個tuple用class實(shí)例來表示,就可以更容易的看出表的結(jié)構(gòu)來:

[圖片上傳失敗...(image-3b0876-1586172584834)]

這就是傳說中的ORM技術(shù):Object-Relational Mapping 圈盔,把關(guān)系數(shù)據(jù)庫的表結(jié)構(gòu)映射到對象上豹芯。但是由誰來做這個轉(zhuǎn)化呢?所以O(shè)RM框架應(yīng)運(yùn)而生驱敲。目前來說也是描述程序中對象和數(shù)據(jù)庫中數(shù)據(jù)記錄之間的映射關(guān)系的統(tǒng)稱铁蹈,是一種進(jìn)行程序和數(shù)據(jù)庫之間數(shù)據(jù)持久化的一種編程思想。

ORM思想的核心是隱藏了數(shù)據(jù)訪問細(xì)節(jié)众眨,提供了通用的數(shù)據(jù)庫交互握牧,并且完全不用考慮SQL語句容诬,從而快速開發(fā)。

一句話解釋ORM就是:一種可以把model中的模型和數(shù)據(jù)庫中的一條數(shù)據(jù)相互轉(zhuǎn)換的工具沿腰。

舉個例子:

[圖片上傳失敗...(image-3804b0-1586172584834)]

[圖片上傳失敗...(image-5837f6-1586172584834)]

在Python中览徒,最有名的ORM框架是SQLAlchemy。我們來看看其語法颂龙。

一习蓬,初始化數(shù)據(jù)庫連接

SQLAlchemy本身無法操作數(shù)據(jù)庫,其必須通過pymysql等第三方插件措嵌。上圖中Dialect用于和數(shù)據(jù)API進(jìn)行交流躲叼,根據(jù)配置文件的不同調(diào)用不同的數(shù)據(jù)庫API,從而實(shí)現(xiàn)對數(shù)據(jù)庫的操作企巢。

使用sqlalchemy進(jìn)行數(shù)據(jù)庫操作枫慷,首先我們需要建立一個指定數(shù)據(jù)庫的鏈接引擎對象,而建立引擎對象的方式被封裝在了sqlalchemy.create_engine函數(shù)中浪规,通過指定的數(shù)據(jù)庫連接信息即可創(chuàng)建或听。

create_engine()用來初始化數(shù)據(jù)庫連接。SQLAlchemy用一個字符串表示連接信息:

'數(shù)據(jù)庫類型+數(shù)據(jù)庫驅(qū)動名稱://用戶名:口令@機(jī)器地址:端口號/數(shù)據(jù)庫名'

你只需要根據(jù)需要替換掉用戶名笋婿,口令等信息即可誉裆。舉個例子:

初始化數(shù)據(jù)庫鏈接

engine = create_engine('mysql+mysqlconnector://root:123456@localhost:3306/test')

我使用了mysql數(shù)據(jù)庫,數(shù)據(jù)庫連接框架用的是mysqlconnector萌抵,用戶名為root,密碼是123456元镀,端口號是localhost(127.0.0.1)绍填,端口號是3306(mysql服務(wù)器默認(rèn)端口號),test是數(shù)據(jù)庫的名字栖疑。

二讨永,創(chuàng)建user模型及其數(shù)據(jù)庫建表操作

2.1,安裝SQLAlchemy

如果沒有安裝SQLAlchemy請先安裝遇革,這個不是python自帶的卿闹。

pip install sqlalchemy

2.2,數(shù)據(jù)庫建表

在test數(shù)據(jù)庫中萝快,創(chuàng)建user表锻霎,SQL如下:

create table user (id varchar(20) primary key, name varchar(20))

創(chuàng)建表,表名為user揪漩,表中有兩個字段旋恼。一個是id,varchar類型奄容,最多支持20個字符冰更,設(shè)置為主鍵产徊,另一個是name,varchar類型蜀细,最多支持20個字符舟铜。

(PS:主鍵時唯一的,當(dāng)你重復(fù)插入時會報錯奠衔,并終止插入操作)谆刨。

插入數(shù)據(jù),如下:

[圖片上傳失敗...(image-2c6faa-1586172584834)]

更改表名

alter table origin_name rename to new_name;

2.3涣觉,創(chuàng)建user模型

在model.py中創(chuàng)建 一個User類痴荐,用來和User表中的字段進(jìn)行關(guān)聯(lián)。

[圖片上傳失敗...(image-72132b-1586172584834)]

這段代碼的意思官册,User類的字段名和表中完全一致生兆,而且字段的屬性也一樣,以id字段為例膝宁,表中id的屬性是Varchar(20)鸦难,primary key,模型中String(20)员淫,primary_key=True合蔽。我們可以清洗的看到varchar在程序中對應(yīng)String,primary_key對應(yīng)程序中的primary_key屬性介返,而且是一個bool類型拴事。

(PS:這里的String是sqlAlchemy中的一個類,這樣類似的類我們還會用到Column)

2.4圣蝎,Column類的學(xué)習(xí)

構(gòu)建函數(shù)為

Column.init(self, name, type_, *args, **kwargs)

name 列名

type_ 類型 刃宵,更多類型SQLAlchemy.types

下面是*args參數(shù)定義

Constraint(約束)

ForeignKey(外鍵)

ColumnDefault(默認(rèn))

Sequenceobjects(序列)定義

下面是**kwargs參數(shù)定義

primary_key 如果為True,則是主鍵

nullable 是否可謂Null徘公,默認(rèn)是True

default 默認(rèn)值牲证,默認(rèn)是None

index 是否是索引,默認(rèn)是True

unique 是否唯一鍵关面,默認(rèn)是False

onupdate 指定一個更新時候的值坦袍,這個操作是定義在SQLAlchemy中,不是在數(shù)據(jù)庫里的等太,當(dāng)更新一條數(shù)據(jù)時設(shè)置捂齐,大部分用于update Time這類字段

autoincrement 設(shè)置為整型自動增長,只有沒有默認(rèn)值缩抡,并且是Integer類型辛燥,默認(rèn)是True

quote 如果列明是關(guān)鍵字,則強(qiáng)制轉(zhuǎn)義,默認(rèn)False

三挎塌,CRUD(Create Read Update Delete徘六,增查改刪)

在SQLAlchemy中,增刪改查操作是通過一個session對象(DBSession是由sessionmaker創(chuàng)建的)來完成的榴都。

3.1待锈,初始化DBSession,連接會話

我們的程序中的對象要使用sqlalchemy的管理嘴高,實(shí)現(xiàn)對象的ORM操作竿音,就需要按照框架指定的方式進(jìn)行類型的創(chuàng)建操作,SQLAlchemy封裝了基礎(chǔ)類的聲明操作和字段屬性的定義限制方式拴驮,開發(fā)人員要做的事情就是引入需要的模塊并在創(chuàng)建對象的時候使用他們即可春瞬。

基礎(chǔ)類封裝在sqlalchemy.ext.declarative_base模塊中,字段屬性的定義封裝在SQLAlchemy模塊中套啤,通過sqlalchemy.Column定義屬性宽气,通過封裝的Integer,String潜沦,F(xiàn)loat等定義屬性的限制萄涯。

首先我們需要創(chuàng)建DBSession,在此基礎(chǔ)上就可以進(jìn)行增刪改查操作了唆鸡。

[圖片上傳失敗...(image-132536-1586172584834)]

上面的代碼完成SQLAlchemy的初始化和具體每個表的class定義涝影。如果有多個表,就繼續(xù)定義其他class争占。

注意:如果在創(chuàng)建會話的時候還沒有指定數(shù)據(jù)庫引擎燃逻,可以通過如下的方式完成會話:

3.2,添加操作

程序中存在一個對象Object數(shù)據(jù)臂痕,通過ORM核心模塊進(jìn)行增加的函數(shù)定義將對象保存在數(shù)據(jù)庫的操作過程伯襟,就是增加操作。比如注冊操作中刻蟹,通過用戶輸入的賬號密碼等信息創(chuàng)建了一個獨(dú)立的對象逗旁,通過add()函數(shù)將對象增加保存到數(shù)據(jù)庫中嘿辟,數(shù)據(jù)庫中就存在用戶這個對象數(shù)據(jù)了舆瘪。

下面,我們看看如何向數(shù)據(jù)庫表中添加一行記錄红伦。

由于有ORM英古,我們向數(shù)據(jù)庫表中添加一行記錄,可以視為添加一個User對象:

[圖片上傳失敗...(image-919e2c-1586172584834)]

可見昙读,關(guān)鍵是獲取session召调,然后把對象添加到session,最后提交并關(guān)閉。DBSession對象可視為當(dāng)前數(shù)據(jù)庫連接唠叛。

3.3只嚣,查詢操作

查詢時通過Session的query()方法創(chuàng)建一個查詢對象,這個函數(shù)的參數(shù)可以是任何類或者類的描述的集合艺沼。查詢出來的數(shù)據(jù)是一個對象册舞,直接通過對象的屬性調(diào)用。

如何從數(shù)據(jù)庫表中查詢數(shù)據(jù)呢障般?有了ORM调鲸,查詢出來的可以不再是tuple,而是User對象挽荡。SQLAlchemy提供的查詢接口如下:

可見藐石,ORM就是把數(shù)據(jù)庫表的行與相應(yīng)的對象建立關(guān)聯(lián),互相轉(zhuǎn)換定拟。

由于關(guān)系數(shù)據(jù)庫的多個表還可以用外鍵實(shí)現(xiàn)一對多于微,多對多等關(guān)聯(lián),相應(yīng)的办素,ORM框架也可以提供兩個對象之間的一對多角雷,多對多等功能。

例如性穿,如果一個User擁有多個Book勺三,就可以定義一對多關(guān)系如下:

當(dāng)我們查詢一個User對象時,該對象的books屬性將返回一個包含若干個Book對象的list .

3.4需曾,更新操作

程序中存在的一個對象Object數(shù)據(jù)吗坚,有自己的id編號(可以使程序中自行賦值定義,更多的操作是從數(shù)據(jù)庫中查詢出來存在的一個對象)呆万,通過ORM核心模塊進(jìn)行修改函數(shù)的定義將對象改變的數(shù)據(jù)更新到數(shù)據(jù)庫中已經(jīng)存在的記錄中的過程商源,就是更新操作。比如用戶更改登錄密碼操作時谋减,根據(jù)程序中查詢得到的一個用戶{id編號牡彻,賬號,密碼}出爹,在程序中通過改變其密碼屬性數(shù)據(jù)庄吼,然后通過update()函數(shù)將改變的數(shù)據(jù)更新保存到數(shù)據(jù)庫中,數(shù)據(jù)庫原來的數(shù)據(jù)就發(fā)生了新的改變严就。

更新操作要多一步总寻,就是要先根據(jù)篩選條件拿到要更改的對象,然后給對象賦值梢为,再次提交(commit)即可渐行。

3.5轰坊,刪除操作

程序中存在的一個對象或者已知的id編號,通過主鍵編號或者對象的任意屬性進(jìn)行數(shù)據(jù)庫中數(shù)據(jù)記錄的刪除的操作過程稱為刪除操作祟印。如管理員刪除某個會員賬號的操作肴沫,通過獲取要刪除會員的賬號,然后通過delete()函數(shù)將要刪除的會員信息告知數(shù)據(jù)庫執(zhí)行刪除操作蕴忆,數(shù)據(jù)庫中的某條存在的數(shù)據(jù)記錄就被刪除掉了樊零。

3.6,代碼整合

四孽文,查詢對象Query

Session是sqlalchemy和數(shù)據(jù)庫交互的橋梁驻襟,Session提供了一個Query對象實(shí)現(xiàn)數(shù)據(jù)庫中數(shù)據(jù)的查詢操作。

4.1芋哭,常規(guī)查詢query

直接指定類型進(jìn)行查詢

4.2沉衣,指定排序查詢

通過類型的屬性指定排序方式

4.5,指定類型別名

對于類型名稱較長的情況减牺,同樣可以指定別名進(jìn)行處理

4.6豌习,切片查詢

對于經(jīng)常用于分頁操作單額切片查詢,在使用過程中直接使用python內(nèi)置的切片即可拔疚。

1user_list = session.query(User).all()[1:3]

五肥隆,條件篩選filter

上面主要對數(shù)據(jù)查詢對象query有一個比較直觀的感受和操作,在實(shí)際使用過程中經(jīng)常用到條件查詢稚失,主要通過filter 和 filter_by 進(jìn)行操作栋艳,下面重點(diǎn)學(xué)習(xí)最為頻繁的filter條件篩選函數(shù)。

5.1句各,等值條件——equals / not equals

5.2吸占,模糊條件——like

1session.query(User).filter(User.name.like(‘%james%’))

5.3,范圍條件——in / not in

5.4凿宾,空值條件——is null / is not null

5.5矾屯,并且條件——and

5.6,或者條件——or

5.7初厚,SQL語句查詢

某些特殊的情況下件蚕,我們也可能在自己的程序中直接使用sql語句進(jìn)行操作。

5.8产禾,filter() 和 filter_by()的區(qū)別

首先看一個例子:

結(jié)果如下:

1001 James

1001 James

所以排作,從例子可以看出,filter可以像寫SQL的where條件那樣寫 < , > 等條件下愈,但引用列名時纽绍,需要通過類名蕾久,屬性名的方式势似。 filter_by可以使用python的正常參數(shù)傳遞條件拌夏,指定列名時,不需要額外指定類名履因,參數(shù)名對應(yīng)類中的屬性名障簿,不能用 < , > 等條件。

filter不支持組合查詢栅迄,只能連續(xù)調(diào)用filter變相實(shí)現(xiàn)站故,filter_by的參數(shù)是 **kwargs,直接支持組合查詢毅舆。

六西篓,查詢結(jié)果

6.1,all()函數(shù)返回查詢列表

返回一個列表憋活,可以通過遍歷列表獲取每個對象岂津。

session.query(User).all()

6.2,filter()函數(shù)返回單項數(shù)據(jù)的列表生成器

session.query(User).filter(..)

6.3悦即,one() / one_or_none() / scalar() 返回單獨(dú)的一個數(shù)據(jù)對象

one()返回且僅返回一個查詢結(jié)果吮成,當(dāng)結(jié)果數(shù)量不足或者多余一個時會報錯。

session.query(User).filter(..).one()/one_or_none()/scalar()

6.4辜梳,first() 返回一個單項結(jié)果

返回至多一個結(jié)果粱甫,而且以單項形式,而不是只有一個元素的tuple形式返回作瞄。

session.query(User).filter(User.id > 1001).first()

七茶宵,遇到的問題及其解決方法

7.1 sqlalchemy查詢中,如果沒有符合條件的結(jié)果宗挥,會返回一個空的對象节预,如何判斷這個對象是空的?

解決問題的代碼:

八属韧,擴(kuò)展知識

8.1 Python雙下劃線開頭的函數(shù)和變量

python 用下劃線作為變量前綴和后綴指定特殊變量安拟。

__XXX 不能用 ‘ from module import * ’ 導(dǎo)入

XXX 系統(tǒng)定義名稱

__XXX 類中的私有變量名

核心風(fēng)格:避免用下劃線作為變量名的開始。

因?yàn)橄聞澗€對解釋器有特殊的意義宵喂,而且是內(nèi)建標(biāo)識符所使用的符號糠赦,我們建議程序員避免使用下劃線作為變量名的開始。一般來說锅棕,變量名__XXX 被看做是“私有”的拙泽,在模塊或類外不可以使用。當(dāng)變量是私有的時候裸燎,用XXX來表示變量是很好地習(xí)慣顾瞻。因?yàn)樽兞棵?strong>XXX對python來說有特殊含義,對于普通的變量應(yīng)當(dāng)避免這種命名風(fēng)格德绿。

“單下劃線”開始的成員變量叫做保護(hù)變量荷荤,意思是只有類對象和子類對象自己能訪問到這些變量退渗;

“雙下劃線”開始的是私有成員,意思是只有類對象自己能訪問蕴纳,連子類對象也不能訪問到這個數(shù)據(jù)会油。

以單下劃線開頭(__foo)的代表不能直接訪問的類屬性,需通過類提供的接口進(jìn)行訪問古毛,不能用“from XXX import * ”而導(dǎo)入翻翩;

以雙下劃線開頭的(__foo)代表類的私有成員;

以雙下劃線開頭和結(jié)尾的(foo)代表python里特殊方法專用的標(biāo)識稻薇,如init() 代表類的構(gòu)造函數(shù)嫂冻。

8.2 if name == ''main''

所有的python模塊都是對象并且有幾個有用的屬性,你可以使用這些屬性方便的測試你所書寫的模塊塞椎。

模塊是對象絮吵,并且所有的模塊都有一個內(nèi)置屬性name。一個模塊的name的值要你您如何應(yīng)用模塊忱屑。如果import模塊蹬敲,那么name的值通常為模塊的文件名,不帶路徑或者文件擴(kuò)展名莺戒。但是我們也可以像一個標(biāo)準(zhǔn)的程序一樣直接運(yùn)行模塊伴嗡,在這種情況下name的值將會是一個特別的缺省值:main

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末从铲,一起剝皮案震驚了整個濱河市瘪校,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌名段,老刑警劉巖阱扬,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伸辟,居然都是意外死亡麻惶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門信夫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窃蹋,“玉大人,你說我怎么就攤上這事静稻【唬” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵振湾,是天一觀的道長杀迹。 經(jīng)常有香客問我,道長押搪,這世上最難降的妖魔是什么树酪? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任浅碾,我火速辦了婚禮,結(jié)果婚禮上嗅回,老公的妹妹穿的比我還像新娘。我一直安慰自己摧茴,他們只是感情好绵载,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苛白,像睡著了一般娃豹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上购裙,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天懂版,我揣著相機(jī)與錄音,去河邊找鬼躏率。 笑死躯畴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的薇芝。 我是一名探鬼主播蓬抄,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼夯到!你這毒婦竟也來了嚷缭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤耍贾,失蹤者是張志新(化名)和其女友劉穎阅爽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荐开,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡付翁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晃听。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胆敞。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖杂伟,靈堂內(nèi)的尸體忽然破棺而出移层,到底是詐尸還是另有隱情,我是刑警寧澤赫粥,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布观话,位于F島的核電站,受9級特大地震影響越平,放射性物質(zhì)發(fā)生泄漏频蛔。R本人自食惡果不足惜灵迫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晦溪。 院中可真熱鬧瀑粥,春花似錦、人聲如沸三圆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舟肉。三九已至修噪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間路媚,已是汗流浹背办陷。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工病游, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呵曹,地道東北人酱讶。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像裤园,于是被迫代替她去往敵國和親弛矛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • orm操作是所有完整軟件中后端處理最重要的一部分比然,主要完成了后端程序和數(shù)據(jù)庫之間的數(shù)據(jù)同步和持久化的操作丈氓,本文基于...
    大熊_7d48閱讀 5,031評論 1 13
  • 轉(zhuǎn)載,覺得這篇寫 SQLAlchemy Core强法,寫得非常不錯万俗。不過后續(xù)他沒寫SQLAlchemy ORM... ...
    非夢nj閱讀 5,411評論 1 14
  • SQLAlchemy介紹和基本使用 數(shù)據(jù)庫時一個網(wǎng)站的基礎(chǔ),在 flask 中可以自由的使用MySQL饮怯、Postg...
    寬哥好閱讀 1,258評論 0 4
  • pip install sqlalchemy 1.安裝mysqlapt-get install mysql-ser...
    殘風(fēng)疏影閱讀 1,161評論 0 1
  • 這本教科書終于讀完了也闰歪,要是不是跟著讀書小組我最多看兩頁你信不信?哈哈哈蓖墅,真的是有點(diǎn)專業(yè)有點(diǎn)教科書库倘,不過,這種類型...
    易妍辰閱讀 2,414評論 0 0