orm操作是所有完整軟件中后端處理最重要的一部分悟衩,主要完成了后端程序和數(shù)據(jù)庫之間的數(shù)據(jù)同步和持久化的操作藕施,本文基于sqlalchemy官方文檔進(jìn)行整理,完成sqlalchemy的核心操作
目錄
什么是ORM?
常見的ORM操作流程和步驟?
sqlalchemy基礎(chǔ)操作?
1 什么是ORM?
2 常見的ORM操作流程和步驟?
3 sqlalchemy基礎(chǔ)操作?
3.1. 安裝 3
3.2. 連接引擎 3
3.3. 連接會(huì)話 4
3.4. ORM之Object操作 4
3.4.1. 基礎(chǔ)類 4
3.4.2. 數(shù)據(jù)類型創(chuàng)建 5
3.4.3. 數(shù)據(jù)類型映射操作 5
3.5. 增加和更新 6
3.6. 查詢對(duì)象Query 6
3.6.1. 常規(guī)查詢query 6
3.6.2. 指定排序查詢 6
3.6.3. 指定列查詢 7
3.6.4. 指定列屬性別名 7
3.6.5. 指定類型別名 7
3.6.6. 切片查詢 7
3.7. 條件篩選filter 7
3.7.1. 等值條件——equals / not equals 8
3.7.2. 模糊條件——like 8
3.7.3. 范圍條件——in / not in 8
3.7.4. 空值條件——is null / is not null 8
3.7.5. 并且條件——AND 8
3.7.6. 或者條件——OR 9
3.7.7. SQL語句查詢 9
3.8. 查詢結(jié)果 9
3.8.1. all()函數(shù)返回查詢列表 9
3.8.2. filter()函數(shù)返回單項(xiàng)數(shù)據(jù)的列表生成器 9
3.8.3. one()/one_or_none()/scalar()返回單獨(dú)的一個(gè)數(shù)據(jù)對(duì)象 9
1. 什么是ORM
ORM:Object Relation Mapping督暂,最初主要描述的是程序中的Object對(duì)象和關(guān)系型數(shù)據(jù)庫中Rlation關(guān)系(表)之間的映射關(guān)系辜限,目前來說也是描述程序中對(duì)象和數(shù)據(jù)庫中數(shù)據(jù)記錄之間的映射關(guān)系的統(tǒng)稱皇拣,是一種進(jìn)行程序和數(shù)據(jù)庫之間數(shù)據(jù)持久化的一種編程思想。
2. 常見的ORM操作流程和步驟
常規(guī)情況下薄嫡,軟件程序中的ORM操作主要有四個(gè)操作場景:增氧急、刪、改毫深、查
核心操作一般會(huì)區(qū)分為:增刪改态蒂、查詢
增刪改操作
增加操作:程序中存在的一個(gè)對(duì)象Object數(shù)據(jù),通過[ORM]核心模塊進(jìn)行增加的函數(shù)定義將對(duì)象保存到數(shù)據(jù)庫的操作過程费什;如~注冊(cè)操作中钾恢,通過用戶輸入的賬號(hào)密碼等信息創(chuàng)建了一個(gè)獨(dú)立的對(duì)象,通過add()函數(shù)將對(duì)象增加保存到數(shù)據(jù)庫中鸳址,數(shù)據(jù)庫中就存在用戶這個(gè)對(duì)象數(shù)據(jù)了瘩蚪。
修改操作:程序中存在的一個(gè)對(duì)象Object數(shù)據(jù),有自己的id編號(hào)(可以是程序中自行賦值定義稿黍、更多的操作是從數(shù)據(jù)庫中查詢出來存在的一個(gè)對(duì)象)疹瘦,通過[ORM]核心模塊進(jìn)行修改函數(shù)的定義將對(duì)象改變的數(shù)據(jù)更新到數(shù)據(jù)庫中已經(jīng)存在的記錄中的過程;如~用戶更改登錄密碼操作時(shí)巡球,根據(jù)程序中查詢得到的一個(gè)用戶[id編號(hào)言沐、賬號(hào)、密碼酣栈、..]险胰,在程序中通過改變其密碼屬性數(shù)據(jù),然后通過update()函數(shù)將改變的數(shù)據(jù)更新保存到數(shù)據(jù)庫中矿筝,數(shù)據(jù)庫中原來的數(shù)據(jù)就發(fā)生了新的改變起便。
刪除操作:程序中存在的一個(gè)對(duì)象或者已知的id編號(hào),通過主鍵編號(hào)或者對(duì)象的任意屬性進(jìn)行數(shù)據(jù)庫中數(shù)據(jù)記錄的刪除的操作過程窖维;如~管理員刪除某個(gè)會(huì)員賬號(hào)的操作榆综,通過獲取要?jiǎng)h除會(huì)員的賬號(hào),然后通過delete()函數(shù)將要?jiǎng)h除的會(huì)員信息告知數(shù)據(jù)庫執(zhí)行刪除操作铸史,數(shù)據(jù)庫中的某條存在的數(shù)據(jù)記錄就被刪除掉了鼻疮。
3. sqlalchemy基礎(chǔ)操作
ORM操作在實(shí)際項(xiàng)目中的應(yīng)用非常多,涉及到的框架也是根據(jù)不同的項(xiàng)目有不同的處理模塊琳轿,不過操作流程和步驟都是大同小異基本沒有什么太大變化判沟,唯一需要注意的就是在實(shí)際操作過程中你要使用的ORM框架的處理性能和是否支持事務(wù)震贵、是否支持分布式等特性來進(jìn)行確定使用哪個(gè)ORM框架進(jìn)行操作,一般在python程序中ORM操作都是對(duì)mysqldb和pymysql這樣的底層模塊進(jìn)行的封裝處理水评。例如文章中要講解的sqlalchemy就是底層封裝mysqldb的實(shí)現(xiàn)猩系,不過我們的在使用過程中需要使用pymysql進(jìn)行替代。
3.1. 安裝
首先確保你的PC已經(jīng)具備了完善的python開發(fā)環(huán)境
安裝sqlalchemy中燥,執(zhí)行如下命令使用pip安裝即可
$ pip install sqlalchemy
或者執(zhí)行如下命令通過easy_install進(jìn)行安裝
$ easy_install sqlalchemy
安裝完成之后寇甸,可以通過引入sqlalchemy進(jìn)行版本查看,確認(rèn)sqlalchemy安裝成功
>>> import sqlalchemy>>> sqlalchemy.__version__'1.2.0b3'
3.2. 連接引擎
使用sqlalchemy進(jìn)行數(shù)據(jù)庫操作疗涉,首先我們需要建立一個(gè)指定數(shù)據(jù)庫的連接引擎對(duì)象
建立引擎對(duì)象的方式被封裝在了sqlalchemy.create_engine函數(shù)中拿霉,通過指定的數(shù)據(jù)庫連接信息就可以進(jìn)行創(chuàng)建
創(chuàng)建數(shù)據(jù)庫連接引擎時(shí)參數(shù)設(shè)置語法:
dialect[+driver]://user:password@host/dbname[?key=value..]# 引入建立引擎的模塊from sqlalchemy import create_engine# 創(chuàng)建一個(gè)和mysql數(shù)據(jù)庫之間的連接引擎對(duì)象engine = create_engine("mysql://root:root@localhost/py1709",
encoding="utf-8", echo=True)
指定的數(shù)據(jù)庫連接字符串表示了目標(biāo)數(shù)據(jù)庫的配置信息;encoding配置參數(shù)指定了和和數(shù)據(jù)庫之間交換的數(shù)據(jù)的編碼方式咱扣,同時(shí)echo參數(shù)表示隨時(shí)在控制臺(tái)展示和數(shù)據(jù)庫之間交互的各種信息
create_engine()函數(shù)返回的是sqlalchemy最核心的接口之一绽淘,該引擎對(duì)象會(huì)根據(jù)開發(fā)人員指定的數(shù)據(jù)庫進(jìn)行對(duì)應(yīng)的sql api的調(diào)用處理
連接postgresql數(shù)據(jù)庫:
engine = create_engine("postgresql://scott:tiger@localhost/test")
連接mysql數(shù)據(jù)庫:
engine = create_engine("mysql://scott:tiger@hostname/dbname",
encoding='utf-8', echo=True)
其他連接方式請(qǐng)參考官方文檔:http://docs.sqlalchemy.org/en/latest/
3.3. 連接會(huì)話
創(chuàng)建了數(shù)據(jù)庫連接引擎對(duì)象之后,我們需要獲取和指定數(shù)據(jù)庫之間的連接闹伪,通過連接進(jìn)行數(shù)據(jù)庫中數(shù)據(jù)的增刪改查操作沪铭,和數(shù)據(jù)庫的連接我們稱之為和指定數(shù)據(jù)庫之間的會(huì)話,通過指定的一個(gè)模塊
sqlalchemy.sessionmaker進(jìn)行創(chuàng)建# 引入創(chuàng)建session連接會(huì)話需要的處理模塊from sqlalchemy.orm import sessionmaker# 創(chuàng)建一個(gè)連接會(huì)話對(duì)象偏瓤;需要指定是和那個(gè)數(shù)據(jù)庫引擎之間的會(huì)話Session = sessionmaker(bind=engine)session = Session()# 接下來~就可以用過session會(huì)話進(jìn)行數(shù)據(jù)庫的數(shù)據(jù)操作了杀怠。
PS:如果在創(chuàng)建會(huì)話的時(shí)候還沒有指定數(shù)據(jù)庫引擎,可以通過如下的方式完成會(huì)話操作
Session = sessionmaker()..Session.configure(bind=engine)session = Session()..
3.4. ORM之Object操作
我們的程序中的對(duì)象要使用sqlalchemy的管理厅克,實(shí)現(xiàn)對(duì)象的orm操作赔退,就需要按照框架指定的方式進(jìn)行類型的創(chuàng)建操作,sqlalchemy封裝了基礎(chǔ)類的聲明操作和字段屬性的定義限制方式证舟,開發(fā)人員要做的事情就是引入需要的模塊并在創(chuàng)建對(duì)象的時(shí)候使用它們即可
基礎(chǔ)類封裝在sqlalchemy.ext.declarative.declarative_base模塊中
字段屬性的定義封裝在sqlalchemy模塊中硕旗,通過sqlalchemy.Column定義屬性,通過封裝的Integer女责、String漆枚、Float等定義屬性的限制
3.4.1. 基礎(chǔ)類
創(chuàng)建基礎(chǔ)類的方式如下:
# 引入需要的模塊from sqlalchemy.ext.declarative import declarative_base# 創(chuàng)建基礎(chǔ)類BaseModel = declarative_base()
3.4.2. 數(shù)據(jù)類型創(chuàng)建
創(chuàng)建數(shù)據(jù)模型的操作
# 引入需要的模塊from sqlalchemy import Column, String, Integer# 創(chuàng)建用戶類型class User(BaseModel):? ? # 定義和指定數(shù)據(jù)庫表之間的關(guān)聯(lián)? ? __tabelname__ = “user”? ? # 創(chuàng)建字段類型? ? id = Column(Integer, primary_key=True)? ? name = Column(String(50))? ? age = Column(Integer)
PS:定義的數(shù)據(jù)類型必須繼承自之前創(chuàng)建的BaseModel,同時(shí)通過指定tablename確定和數(shù)據(jù)庫中某個(gè)數(shù)據(jù)表之間的關(guān)聯(lián)關(guān)系鲤竹,指定某列類型為primary_key設(shè)定的主鍵浪读,其他就是通過Column指定的自定義屬性了。
sqlalchemy會(huì)根據(jù)指定的tablename和對(duì)應(yīng)的Column列字段構(gòu)建自己的accessors訪問器對(duì)象辛藻,這個(gè)過程可以成為instrumentation,經(jīng)過instrumentation映射的類型既可以進(jìn)行數(shù)據(jù)庫中數(shù)據(jù)的操作了互订。
3.4.3. 數(shù)據(jù)類型映射操作
完成了類的聲明定義之后吱肌,Declarative會(huì)通過python的metaclass對(duì)當(dāng)前類型進(jìn)行操作,根據(jù)定義的數(shù)據(jù)類型創(chuàng)建table對(duì)象仰禽,構(gòu)建程序中類型和數(shù)據(jù)庫table對(duì)象之間的映射mapping關(guān)系
通過類型對(duì)象的metadata可以實(shí)現(xiàn)和數(shù)據(jù)庫之間的交互氮墨,有需要時(shí)可以通過metadata發(fā)起create table操作纺蛆,通過Base.metadata.create_all()進(jìn)行操作,該操作會(huì)檢查目標(biāo)數(shù)據(jù)庫中是否有需要?jiǎng)?chuàng)建的表规揪,不存在的情況下創(chuàng)建對(duì)應(yīng)的表
..if __name__ == “__main__”:Base.metadata.create_all()..
3.5. 增加和更新
下面就是核心的數(shù)據(jù)對(duì)象的處理了桥氏,在程序代碼中根據(jù)定義的數(shù)據(jù)類型創(chuàng)建對(duì)象的方式比較簡單,執(zhí)行如下的操作創(chuàng)建一個(gè)對(duì)象:
$ user = User(name=”tom”, age=18)$ print(user.name)tom
$ print(user.id)None
通過會(huì)話對(duì)象將對(duì)象數(shù)據(jù)持久化到數(shù)據(jù)庫的操作
$ session.add(user)$ print(user.id)None$ session.commit()$ print(user.id)1
3.6. 查詢對(duì)象Query
Session是sqlalchemy和數(shù)據(jù)庫交互的橋梁猛铅,Session提供了一個(gè)Query對(duì)象實(shí)現(xiàn)數(shù)據(jù)庫中數(shù)據(jù)的查詢操作
3.6.1. 常規(guī)查詢query
直接指定類型進(jìn)行查詢
user_list = session.query(User)for user in user_list:? ? print(user.name)
3.6.2. 指定排序查詢
通過類型的屬性指定排序方式
user_list = session.query(User).order_by(User.id) # 默認(rèn)順序user_list = session.query(User).order_by(-User.id) # 指定倒序user_list = session.query(User).order_by(-User.id, User.name) # 多個(gè)字段
3.6.3. 指定列查詢
指定查詢數(shù)據(jù)對(duì)象的屬性字支,查詢目標(biāo)數(shù)據(jù)
user_list = session.query(User, User.name).all()for u in user_list:? ? print(u.User, u.name)
3.6.4. 指定列屬性別名
對(duì)于名稱較長的字段屬性,可以指定名稱在使用時(shí)簡化操作
user_list = session.query(Usre.name.label(‘n’)).all()for user in user_list:? ? print(user.n)
3.6.5. 指定類型別名
對(duì)于類型名稱較長的情況奸忽,同樣可以指定別名進(jìn)行處理
from sqlalchemy.orm import aliased
user_alias = aliased(User, name=’u_alias’)user_list = session.query(u_alias, u_alias.name).all()for u in user_list:? ? print(u.u_alias, u.name)
3.6.6. 切片查詢
對(duì)于經(jīng)常用于分頁操作的切片查詢堕伪,在使用過程中直接使用python內(nèi)置的切片即可
user_list = session.query(User).all()[1:3]..
3.7. 條件篩選filter
前一節(jié)中主要是對(duì)于數(shù)據(jù)查詢對(duì)象query有一個(gè)比較直觀的感受和操作,在實(shí)際使用過程中經(jīng)常用到條件查詢栗菜,主要通過filter和filter_by進(jìn)行操作欠雌,重點(diǎn)講解使用最為頻繁的filter條件篩選函數(shù)
3.7.1. 等值條件——equals / not equals
# equalssession.query(User).filter(User.id == 1) # 相等判斷# not equalssession.query(User).filter(User.name != ‘tom’)# 不等判斷
3.7.2. 模糊條件——like
session.query(User).filter(User.name.like(‘%tom%’))
3.7.3. 范圍條件——in / not in
# INsession.query(User).filter(User.id.in_([1,2,3,4]))session.query(User).filter(User.name.in_([? ? session.query(User.name).filter(User.id.in_[1,2,3,4])]))# NOT INsession.query(User).filter(~User.id.in_([1,2,3]))
3.7.4. 空值條件——is null / is not null
# IS NULLsession.query(User).filter(User.name == None)session.query(User).filter(User.name.is_(None)) # pep8# IS NOT NULLsession.query(User).filter(User.name != None)session.query(User).filter(User.name.isnot(None)) # pep8
3.7.5. 并且條件——AND
from sqlalchemy import and_
session.query(User).filter(User.name=’tom’).filter(User.age=12)session.query(User).filter(User.name=’tom’, User.age=12)session.query(User).filter(and_(User.name=’tom’, User.age=12))
3.7.6. 或者條件——OR
from sqlalchemy import or_
session.query(User).filter(or_(User.name=’tom’, User.name=’jerry’))
3.7.7. SQL語句查詢
某些特殊情況下,我們也可能在自己的程序中直接使用sql語句進(jìn)行操作
from sqlalchemy import text
session.query(User).from_statement(text(‘select * from users where name=:name and age=:age’)).params(name=’tom’, age=12).all()
3.8. 查詢結(jié)果
3.8.1. all()函數(shù)返回查詢列表
session.query(User).all()
[..]
3.8.2. filter()函數(shù)返回單項(xiàng)數(shù)據(jù)的列表生成器
session.query(User).filter(..)
<..>
3.8.3. one()/one_or_none()/scalar()返回單獨(dú)的一個(gè)數(shù)據(jù)對(duì)象
session.query(User).filter(..).one()/one_or_none()/scalar()