溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Flask如何使用SQLAlchemy實現(xiàn)持久化數(shù)據(jù)

發(fā)布時間:2021-07-19 01:34:04 來源:億速云 閱讀:231 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Flask如何使用SQLAlchemy實現(xiàn)持久化數(shù)據(jù)”,在日常操作中,相信很多人在Flask如何使用SQLAlchemy實現(xiàn)持久化數(shù)據(jù)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Flask如何使用SQLAlchemy實現(xiàn)持久化數(shù)據(jù)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

目錄
  • 項目引入flask-sqlalchemy

  • ORM簡介及模型定義

  • 表關(guān)系類型及編碼實現(xiàn)

    • 一對多關(guān)系(多對一關(guān)系)

    • 一對一關(guān)系

    • 多對多關(guān)系

  • 數(shù)據(jù)庫基本操作

    • 插入

    • 更新

    • 查詢

    • 刪除

項目引入flask-sqlalchemy

首先,安裝flask-sqlalchemy擴(kuò)展:

$pip install flask-sqlalchemy

然后,在項目中導(dǎo)入SQLAlchemy類,并實例化應(yīng)用程序使用的數(shù)據(jù)庫(以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對象是SQLAlchemy類的實例,表示程序使用的數(shù)據(jù)庫,同時還獲得了Flask-SQLAlchemy提供的所有功能。

ORM簡介及模型定義

在Python中,可以使用數(shù)據(jù)庫相應(yīng)的包直接操作數(shù)據(jù)庫,如PyMySQL操作MySQL數(shù)據(jù)庫,還有一些數(shù)據(jù)庫抽象層代碼包供選擇,如這里要討論的SQLAlchemy。該抽象包直接處理高等級的Python對象,而不用處理如表這樣的數(shù)據(jù)庫實體。
抽象層,就是所謂的對象關(guān)系映射(ORM),其最大的優(yōu)勢就是:能在用戶不知覺的情況下把高層的面向?qū)ο蟛僮鬓D(zhuǎn)換成低層的數(shù)據(jù)庫指令,極大簡化代碼編寫。SQLAlchemy就是已與Flask很好集成的更高層抽象例子,其還支持多種關(guān)系型數(shù)據(jù)庫引擎。

基于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ù)庫中使用的表名;

db.Column類構(gòu)造函數(shù)的第1個參數(shù)是數(shù)據(jù)庫表列(也是模型屬性)的類型,其余的參數(shù)指定屬性(數(shù)據(jù)庫表列)的配置選項。

2.1 常用的SQLAlchemy列類型

類型名Python類型說明
Integerint普通整數(shù),一般32位
SmallIntegerint取值范圍小的整數(shù),一般16位
BigIntegerint或long不限制精度的整數(shù)
Floatfloat浮點數(shù)
Stringstr變長字符串
Booleanbool布爾值
Datedatetime.date日期
Timedatetime.time時間
DateTimedatetime.datetime日期和時間
Textstr變長字符串,對較長或不限長度的字符串做了優(yōu)化
Numericdecimal.Decimal定點小數(shù)

2.2 常用的SQLAlchemy列選項

選項名說明
primary_key如果設(shè)為True,這列就是表的主鍵
unique如果設(shè)為True,這列不允許重復(fù)值
index如果設(shè)為True,為該列創(chuàng)建索引,提升查詢效率
nullable如果設(shè)為True,這列允許null值,如果設(shè)為false,不允許為空
default為這列定義默認(rèn)值

表關(guān)系類型及編碼實現(xiàn)

關(guān)系型數(shù)據(jù)庫使用關(guān)系把不同表中的行聯(lián)系起來。以上述模型定義代碼為例,假設(shè)角色對用戶是一對多的關(guān)系(即1個角色可屬于多個用戶,而每個用戶只能有1個角色)。

一對多關(guān)系(多對一關(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)建代表實例(記錄或行)的屬性,如上述的users = db.relationship(‘Users', backref=‘role')
db.relationship()的第1個參數(shù)表明這個關(guān)系的另一端是哪個模型,backref參數(shù)向Users模型添加一個role屬性,從而定義反向關(guān)系。通過這一屬性(role)可以替代role_id訪問Roles模型,此時將獲取的是模型對象,而不是外鍵的值。
如何理解上述這段話,可以從下面2句代碼加深:

 users = inst_role.users
 user_role = user.role

通過第1句代碼,可以直接獲得特定角色實例(inst_role)相對應(yīng)的所有users對象,且是以列表形式返回。
通過第2句代碼,可以通過user實例直接獲得該user所對應(yīng)的role對象(1行記錄,而不是Users模式定義的role_id字段值)。

一對一關(guān)系

要定義一對一的關(guān)系,只需基于一對多的模型定義基礎(chǔ)上,給db.relationship()函數(shù)多傳一個關(guān)鍵字表示關(guān)系選項:
users = db.relationship(‘Users', backref=‘role', userlist=False)
一對多與一對一在編碼時,有個點需特別注意:當(dāng)通過“一”的實例(db.relationship定義方)獲取多的一方的對象時:

  • 一對多:users = inst_role.users返回的是對象列表

  • 一對一:users = inst_role.users返回的就是對象,而非列表

多對多關(guān)系

Pending…

數(shù)據(jù)庫基本操作

在Flask-SQLAlchemy中,對數(shù)據(jù)庫所做的改動均是通過數(shù)據(jù)庫“會話”進(jìn)行管理的,會話用db.session表示。如需用db.session.commit()提交對記錄的修改,始終把數(shù)據(jù)庫相關(guān)改動放在會話中提交,可避免因部分更新異常導(dǎo)致數(shù)據(jù)庫中數(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行代碼,實例化2種角色及2個用戶對象(映射至數(shù)據(jù)庫即是給記錄的字段賦值)
5~7行代碼就是將新增角色及用戶操作放在了1個session中,最后再統(tǒng)一提交(commit),可防止因其中某條語句異常而更新部分從而導(dǎo)致數(shù)據(jù)的不一致性。該操作就是將多個原子操作組成一個事務(wù),如果某條更新失敗就會導(dǎo)致整個會話失效。
5~7行還可簡寫成: db.session.add([admin_role, mod_role, john, david])

更新

在Flask-SQLAlchemy中,一條記錄表示為一個對象;記錄的字段表示為對象的屬性,因此要更新字段值,實際上就是對對象的屬性賦值:

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ù)指定條件對原查詢結(jié)果進(jìn)行排序
group_by根據(jù)指定條件對原查詢結(jié)果進(jìn)行分組

2.1 filter與filter_by區(qū)別

2.1.1 語法區(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來實現(xiàn),而filter_by支持組合查詢(下面2條語句效果一樣)

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查詢語句,只需把query對象轉(zhuǎn)換成字符串: str(Users.query.filter_by(role=admin_role))

刪除

執(zhí)行查詢

在查詢上應(yīng)用指定的過濾器后,通過調(diào)用all()觸發(fā)執(zhí)行查詢,常見的觸發(fā)執(zhí)行方法有: 

方法說明
all()查詢所有結(jié)果
first()返回查詢的第1個結(jié)果,沒有返回None
get()返回指定主鍵對應(yīng)的行,沒有返回None
count()返回查詢結(jié)果的數(shù)量
first_or_404()返回查詢的第1個結(jié)果,如果沒有結(jié)果,則終止請求,返回404錯誤響應(yīng)
get_or_404()返回指定主鍵對應(yīng)的行,如果沒找到指定的主鍵,則終止請求,返回404錯誤響應(yīng)
paginate()返回一個paginate對象

4.1 一對多

4.1.1 從“一”獲取對應(yīng)的所有多端對象

users = inst_role.users //直接通過角色對象的users屬性獲取所有屬于該角色的用戶對象
role = inst_user.role  //直接通過用戶實例的role屬性獲取該用戶所屬的角色對象,注意這里獲取的是角色對象,而不僅是角色I(xiàn)D

注:inst_role.users獲取對象時,隱含了調(diào)用all()方法觸發(fā)執(zhí)行,但如果像加一些過濾器(如排序),則需要在db.relationship中添加lazy='dynamic'關(guān)鍵字參數(shù)。然后即可引入過濾器:inst_role.users.order_by(Users.username)

4.2 多對多

Pending…

在Flask-SQLAlchemy中,刪除數(shù)據(jù)庫記錄,可映射至刪除代表該記錄的對象:

db.session.delete(mod_role)
db.session.commit()

到此,關(guān)于“Flask如何使用SQLAlchemy實現(xiàn)持久化數(shù)據(jù)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI