Flask使用SQLAlchemy實(shí)現(xiàn)持久化數(shù)據(jù)
項(xiàng)目引入flask-sqlalchemy
首先,安裝flask-sqlalchemy擴(kuò)展:
$pip install flask-sqlalchemy
然后,在項(xiàng)目中導(dǎo)入SQLAlchemy類,并實(shí)例化應(yīng)用程序使用的數(shù)據(jù)庫(kù)(以mysql為例):
from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://account:password@hostname/database' db = SQLAlchemy(app)
db對(duì)象是SQLAlchemy類的實(shí)例,表示程序使用的數(shù)據(jù)庫(kù),同時(shí)還獲得了Flask-SQLAlchemy提供的所有功能。
ORM簡(jiǎn)介及模型定義
在Python中,可以使用數(shù)據(jù)庫(kù)相應(yīng)的包直接操作數(shù)據(jù)庫(kù),如PyMySQL操作MySQL數(shù)據(jù)庫(kù),還有一些數(shù)據(jù)庫(kù)抽象層代碼包供選擇,如這里要討論的SQLAlchemy。該抽象包直接處理高等級(jí)的Python對(duì)象,而不用處理如表這樣的數(shù)據(jù)庫(kù)實(shí)體。
抽象層,就是所謂的對(duì)象關(guān)系映射(ORM),其最大的優(yōu)勢(shì)就是:能在用戶不知覺的情況下把高層的面向?qū)ο蟛僮鬓D(zhuǎn)換成低層的數(shù)據(jù)庫(kù)指令,極大簡(jiǎn)化代碼編寫。SQLAlchemy就是已與Flask很好集成的更高層抽象例子,其還支持多種關(guān)系型數(shù)據(jù)庫(kù)引擎。
基于SQLAlchemy的模型定義:
class Roles(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
users = db.relationship('Users', backref='role')
class Users(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
__tablename__定義在數(shù)據(jù)庫(kù)中使用的表名;
db.Column類構(gòu)造函數(shù)的第1個(gè)參數(shù)是數(shù)據(jù)庫(kù)表列(也是模型屬性)的類型,其余的參數(shù)指定屬性(數(shù)據(jù)庫(kù)表列)的配置選項(xiàng)。
2.1 常用的SQLAlchemy列類型
| 類型名 | Python類型 | 說明 |
|---|---|---|
| Integer | int | 普通整數(shù),一般32位 |
| SmallInteger | int | 取值范圍小的整數(shù),一般16位 |
| BigInteger | int或long | 不限制精度的整數(shù) |
| Float | float | 浮點(diǎn)數(shù) |
| String | str | 變長(zhǎng)字符串 |
| Boolean | bool | 布爾值 |
| Date | datetime.date | 日期 |
| Time | datetime.time | 時(shí)間 |
| DateTime | datetime.datetime | 日期和時(shí)間 |
| Text | str | 變長(zhǎng)字符串,對(duì)較長(zhǎng)或不限長(zhǎng)度的字符串做了優(yōu)化 |
| Numeric | decimal.Decimal | 定點(diǎn)小數(shù) |
2.2 常用的SQLAlchemy列選項(xiàng)
| 選項(xiàng)名 | 說明 |
|---|---|
| primary_key | 如果設(shè)為True,這列就是表的主鍵 |
| unique | 如果設(shè)為True,這列不允許重復(fù)值 |
| index | 如果設(shè)為True,為該列創(chuàng)建索引,提升查詢效率 |
| nullable | 如果設(shè)為True,這列允許null值,如果設(shè)為false,不允許為空 |
| default | 為這列定義默認(rèn)值 |
表關(guān)系類型及編碼實(shí)現(xiàn)
關(guān)系型數(shù)據(jù)庫(kù)使用關(guān)系把不同表中的行聯(lián)系起來。以上述模型定義代碼為例,假設(shè)角色對(duì)用戶是一對(duì)多的關(guān)系(即1個(gè)角色可屬于多個(gè)用戶,而每個(gè)用戶只能有1個(gè)角色)。
一對(duì)多關(guān)系(多對(duì)一關(guān)系)
在“多”的一方,使用外鍵定義關(guān)系
如在Users模型中,定義role_id列為外鍵,給db.Column構(gòu)造函數(shù)傳遞db.ForeignKey()參數(shù),并將roles.id作為db.ForeignKey()的參數(shù),其表明role_id列的值是roles表中行的id值。
在“一”的一方,基于面向?qū)ο蟮囊暯莿?chuàng)建代表實(shí)例(記錄或行)的屬性,如上述的users = db.relationship(‘Users', backref=‘role')
db.relationship()的第1個(gè)參數(shù)表明這個(gè)關(guān)系的另一端是哪個(gè)模型,backref參數(shù)向Users模型添加一個(gè)role屬性,從而定義反向關(guān)系。通過這一屬性(role)可以替代role_id訪問Roles模型,此時(shí)將獲取的是模型對(duì)象,而不是外鍵的值。
如何理解上述這段話,可以從下面2句代碼加深:
users = inst_role.users user_role = user.role
通過第1句代碼,可以直接獲得特定角色實(shí)例(inst_role)相對(duì)應(yīng)的所有users對(duì)象,且是以列表形式返回。
通過第2句代碼,可以通過user實(shí)例直接獲得該user所對(duì)應(yīng)的role對(duì)象(1行記錄,而不是Users模式定義的role_id字段值)。
一對(duì)一關(guān)系
要定義一對(duì)一的關(guān)系,只需基于一對(duì)多的模型定義基礎(chǔ)上,給db.relationship()函數(shù)多傳一個(gè)關(guān)鍵字表示關(guān)系選項(xiàng):
users = db.relationship(‘Users', backref=‘role', userlist=False)
一對(duì)多與一對(duì)一在編碼時(shí),有個(gè)點(diǎn)需特別注意:當(dāng)通過“一”的實(shí)例(db.relationship定義方)獲取多的一方的對(duì)象時(shí):
- 一對(duì)多:users = inst_role.users返回的是對(duì)象列表
- 一對(duì)一:users = inst_role.users返回的就是對(duì)象,而非列表
多對(duì)多關(guān)系
Pending…
數(shù)據(jù)庫(kù)基本操作
在Flask-SQLAlchemy中,對(duì)數(shù)據(jù)庫(kù)所做的改動(dòng)均是通過數(shù)據(jù)庫(kù)“會(huì)話”進(jìn)行管理的,會(huì)話用db.session表示。如需用db.session.commit()提交對(duì)記錄的修改,始終把數(shù)據(jù)庫(kù)相關(guān)改動(dòng)放在會(huì)話中提交,可避免因部分更新異常導(dǎo)致數(shù)據(jù)庫(kù)中數(shù)據(jù)的不一致性。
插入
admin_role = Roles(name='Admin')
mod_role = Roles(name='Moderator')
john = Users(username='liyu', role=admin_role)
david = Users(username='liji', role=admin_role)
db.session.add(admin_role)
db.session.add(mod_role)
db.session.add(john)
db.session.add(david)
db.session.commit()
前4行代碼,實(shí)例化2種角色及2個(gè)用戶對(duì)象(映射至數(shù)據(jù)庫(kù)即是給記錄的字段賦值)
5~7行代碼就是將新增角色及用戶操作放在了1個(gè)session中,最后再統(tǒng)一提交(commit),可防止因其中某條語(yǔ)句異常而更新部分從而導(dǎo)致數(shù)據(jù)的不一致性。該操作就是將多個(gè)原子操作組成一個(gè)事務(wù),如果某條更新失敗就會(huì)導(dǎo)致整個(gè)會(huì)話失效。
5~7行還可簡(jiǎn)寫成: db.session.add([admin_role, mod_role, john, david])
更新
在Flask-SQLAlchemy中,一條記錄表示為一個(gè)對(duì)象;記錄的字段表示為對(duì)象的屬性,因此要更新字段值,實(shí)際上就是對(duì)對(duì)象的屬性賦值:
admin_role.name = 'Administrator' db.session.add(admin_role) db.session.commit()
查詢
查詢表中所有記錄:模式.query.all()
eg. Roles.query.all()
使用過濾器進(jìn)行更精確查詢
| 過濾器 | 說明 |
|---|---|
| filter | 把過濾器添加到原查詢上 |
| filter_by | 把等值過濾器添加到原查詢上 |
| limit | 使用指定的值限制原查詢返回的結(jié)果數(shù)量 |
| offset | 偏移原查詢返回的結(jié)果 |
| order_by | 根據(jù)指定條件對(duì)原查詢結(jié)果進(jìn)行排序 |
| group_by | 根據(jù)指定條件對(duì)原查詢結(jié)果進(jìn)行分組 |
2.1 filter與filter_by區(qū)別
2.1.1 語(yǔ)法區(qū)別
filter需要用“類名.屬性名”且需用==比較,而filter_by直接用屬性名,比較用=
users = Users.query.filter(Users.id == 1).all() users = Users.query.filter_by(id = 1).all()
2.1.2 組合查詢
filter不支持組合查詢,只能連續(xù)用filter來實(shí)現(xiàn),而filter_by支持組合查詢(下面2條語(yǔ)句效果一樣)
users = Users.query.filter(Users.id == 1).filter(Users.username == 'xxx').all() users = Users.query.filter_by(id = 1, username='xxx').all() # filter_by也支持連續(xù)使用
注:如果要查看SQLAlchemy為查詢生成的原生SQL查詢語(yǔ)句,只需把query對(duì)象轉(zhuǎn)換成字符串: str(Users.query.filter_by(role=admin_role))
刪除
執(zhí)行查詢
在查詢上應(yīng)用指定的過濾器后,通過調(diào)用all()觸發(fā)執(zhí)行查詢,常見的觸發(fā)執(zhí)行方法有:
| 方法 | 說明 |
|---|---|
| all() | 查詢所有結(jié)果 |
| first() | 返回查詢的第1個(gè)結(jié)果,沒有返回None |
| get() | 返回指定主鍵對(duì)應(yīng)的行,沒有返回None |
| count() | 返回查詢結(jié)果的數(shù)量 |
| first_or_404() | 返回查詢的第1個(gè)結(jié)果,如果沒有結(jié)果,則終止請(qǐng)求,返回404錯(cuò)誤響應(yīng) |
| get_or_404() | 返回指定主鍵對(duì)應(yīng)的行,如果沒找到指定的主鍵,則終止請(qǐng)求,返回404錯(cuò)誤響應(yīng) |
| paginate() | 返回一個(gè)paginate對(duì)象 |
4.1 一對(duì)多
4.1.1 從“一”獲取對(duì)應(yīng)的所有多端對(duì)象
users = inst_role.users //直接通過角色對(duì)象的users屬性獲取所有屬于該角色的用戶對(duì)象 role = inst_user.role //直接通過用戶實(shí)例的role屬性獲取該用戶所屬的角色對(duì)象,注意這里獲取的是角色對(duì)象,而不僅是角色I(xiàn)D
注:inst_role.users獲取對(duì)象時(shí),隱含了調(diào)用all()方法觸發(fā)執(zhí)行,但如果像加一些過濾器(如排序),則需要在db.relationship中添加lazy='dynamic'關(guān)鍵字參數(shù)。然后即可引入過濾器:inst_role.users.order_by(Users.username)
4.2 多對(duì)多
Pending…
在Flask-SQLAlchemy中,刪除數(shù)據(jù)庫(kù)記錄,可映射至刪除代表該記錄的對(duì)象:
db.session.delete(mod_role) db.session.commit()
到此這篇關(guān)于Flask使用SQLAlchemy實(shí)現(xiàn)持久化數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Flask SQLAlchemy持久化數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python Pandas創(chuàng)建Dataframe數(shù)據(jù)框的六種方法匯總
這篇文章主要介紹了Python中的Pandas創(chuàng)建Dataframe數(shù)據(jù)框的六種方法,創(chuàng)建Dataframe主要是使用pandas中的DataFrame函數(shù),其核心就是第一個(gè)參數(shù):data,傳入原始數(shù)據(jù),因此我們可以據(jù)此給出六種創(chuàng)建Dataframe的方法,需要的朋友可以參考下2023-05-05
Python?pandas找出、刪除重復(fù)的數(shù)據(jù)實(shí)例
在面試中很可能遇到給定一個(gè)含有重復(fù)元素的列表,刪除其中重復(fù)的元素,下面這篇文章主要給大家介紹了關(guān)于Python?pandas找出、刪除重復(fù)數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
pycharm2022沒有manage repositories配置鏡像源的解決方法
本文主要介紹了pycharm2022沒有manage repositories配置鏡像源的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
使用Python實(shí)現(xiàn)操作控制鼠標(biāo)和鍵盤
Python 有很多的庫(kù)可以實(shí)現(xiàn)各種各樣的功能,比如使用 pynput 操作,下面小編就來和大家詳細(xì)介紹一下如何使用pynput進(jìn)行操作控制鼠標(biāo)和鍵盤吧2024-02-02
Python實(shí)現(xiàn)PS濾鏡中馬賽克效果示例
這篇文章主要介紹了Python實(shí)現(xiàn)PS濾鏡中馬賽克效果,涉及Python基于skimage庫(kù)的圖形馬賽克效果相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-01-01
在Python的框架中為MySQL實(shí)現(xiàn)restful接口的教程
這篇文章主要介紹了在Python的框架中為MySQL實(shí)現(xiàn)restful接口的教程,文中的示例基于Flask和Django框架,需要的朋友可以參考下2015-04-04

