您好,登錄后才能下訂單哦!
這篇文章主要介紹“Flask如何使用SQLAlchemy實現持久化數據”,在日常操作中,相信很多人在Flask如何使用SQLAlchemy實現持久化數據問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Flask如何使用SQLAlchemy實現持久化數據”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
項目引入flask-sqlalchemy
ORM簡介及模型定義
表關系類型及編碼實現
一對多關系(多對一關系)
一對一關系
多對多關系
數據庫基本操作
插入
更新
查詢
刪除
首先,安裝flask-sqlalchemy擴展:
$pip install flask-sqlalchemy
然后,在項目中導入SQLAlchemy類,并實例化應用程序使用的數據庫(以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類的實例,表示程序使用的數據庫,同時還獲得了Flask-SQLAlchemy提供的所有功能。
在Python中,可以使用數據庫相應的包直接操作數據庫,如PyMySQL操作MySQL數據庫,還有一些數據庫抽象層代碼包供選擇,如這里要討論的SQLAlchemy。該抽象包直接處理高等級的Python對象,而不用處理如表這樣的數據庫實體。
抽象層,就是所謂的對象關系映射(ORM),其最大的優勢就是:能在用戶不知覺的情況下把高層的面向對象操作轉換成低層的數據庫指令,極大簡化代碼編寫。SQLAlchemy就是已與Flask很好集成的更高層抽象例子,其還支持多種關系型數據庫引擎。
基于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__定義在數據庫中使用的表名;
db.Column類構造函數的第1個參數是數據庫表列(也是模型屬性)的類型,其余的參數指定屬性(數據庫表列)的配置選項。
2.1 常用的SQLAlchemy列類型
類型名 | Python類型 | 說明 |
---|---|---|
Integer | int | 普通整數,一般32位 |
SmallInteger | int | 取值范圍小的整數,一般16位 |
BigInteger | int或long | 不限制精度的整數 |
Float | float | 浮點數 |
String | str | 變長字符串 |
Boolean | bool | 布爾值 |
Date | datetime.date | 日期 |
Time | datetime.time | 時間 |
DateTime | datetime.datetime | 日期和時間 |
Text | str | 變長字符串,對較長或不限長度的字符串做了優化 |
Numeric | decimal.Decimal | 定點小數 |
2.2 常用的SQLAlchemy列選項
選項名 | 說明 |
---|---|
primary_key | 如果設為True,這列就是表的主鍵 |
unique | 如果設為True,這列不允許重復值 |
index | 如果設為True,為該列創建索引,提升查詢效率 |
nullable | 如果設為True,這列允許null值,如果設為false,不允許為空 |
default | 為這列定義默認值 |
關系型數據庫使用關系把不同表中的行聯系起來。以上述模型定義代碼為例,假設角色對用戶是一對多的關系(即1個角色可屬于多個用戶,而每個用戶只能有1個角色)。
在“多”的一方,使用外鍵定義關系
如在Users模型中,定義role_id列為外鍵,給db.Column構造函數傳遞db.ForeignKey()參數,并將roles.id作為db.ForeignKey()的參數,其表明role_id列的值是roles表中行的id值。
在“一”的一方,基于面向對象的視角創建代表實例(記錄或行)的屬性,如上述的users = db.relationship(‘Users', backref=‘role')
db.relationship()的第1個參數表明這個關系的另一端是哪個模型,backref參數向Users模型添加一個role屬性,從而定義反向關系。通過這一屬性(role)可以替代role_id訪問Roles模型,此時將獲取的是模型對象,而不是外鍵的值。
如何理解上述這段話,可以從下面2句代碼加深:
users = inst_role.users user_role = user.role
通過第1句代碼,可以直接獲得特定角色實例(inst_role)相對應的所有users對象,且是以列表形式返回。
通過第2句代碼,可以通過user實例直接獲得該user所對應的role對象(1行記錄,而不是Users模式定義的role_id字段值)。
要定義一對一的關系,只需基于一對多的模型定義基礎上,給db.relationship()函數多傳一個關鍵字表示關系選項:
users = db.relationship(‘Users', backref=‘role', userlist=False)
一對多與一對一在編碼時,有個點需特別注意:當通過“一”的實例(db.relationship定義方)獲取多的一方的對象時:
一對多:users = inst_role.users返回的是對象列表
一對一:users = inst_role.users返回的就是對象,而非列表
Pending…
在Flask-SQLAlchemy中,對數據庫所做的改動均是通過數據庫“會話”進行管理的,會話用db.session表示。如需用db.session.commit()提交對記錄的修改,始終把數據庫相關改動放在會話中提交,可避免因部分更新異常導致數據庫中數據的不一致性。
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個用戶對象(映射至數據庫即是給記錄的字段賦值)
5~7行代碼就是將新增角色及用戶操作放在了1個session中,最后再統一提交(commit),可防止因其中某條語句異常而更新部分從而導致數據的不一致性。該操作就是將多個原子操作組成一個事務,如果某條更新失敗就會導致整個會話失效。
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()
使用過濾器進行更精確查詢
過濾器 | 說明 |
---|---|
filter | 把過濾器添加到原查詢上 |
filter_by | 把等值過濾器添加到原查詢上 |
limit | 使用指定的值限制原查詢返回的結果數量 |
offset | 偏移原查詢返回的結果 |
order_by | 根據指定條件對原查詢結果進行排序 |
group_by | 根據指定條件對原查詢結果進行分組 |
2.1 filter與filter_by區別
2.1.1 語法區別
filter需要用“類名.屬性名”且需用==比較,而filter_by直接用屬性名,比較用=
users = Users.query.filter(Users.id == 1).all() users = Users.query.filter_by(id = 1).all()
2.1.2 組合查詢
filter不支持組合查詢,只能連續用filter來實現,而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也支持連續使用
注:如果要查看SQLAlchemy為查詢生成的原生SQL查詢語句,只需把query對象轉換成字符串: str(Users.query.filter_by(role=admin_role))
執行查詢
在查詢上應用指定的過濾器后,通過調用all()觸發執行查詢,常見的觸發執行方法有:
方法 | 說明 |
---|---|
all() | 查詢所有結果 |
first() | 返回查詢的第1個結果,沒有返回None |
get() | 返回指定主鍵對應的行,沒有返回None |
count() | 返回查詢結果的數量 |
first_or_404() | 返回查詢的第1個結果,如果沒有結果,則終止請求,返回404錯誤響應 |
get_or_404() | 返回指定主鍵對應的行,如果沒找到指定的主鍵,則終止請求,返回404錯誤響應 |
paginate() | 返回一個paginate對象 |
4.1 一對多
4.1.1 從“一”獲取對應的所有多端對象
users = inst_role.users //直接通過角色對象的users屬性獲取所有屬于該角色的用戶對象 role = inst_user.role //直接通過用戶實例的role屬性獲取該用戶所屬的角色對象,注意這里獲取的是角色對象,而不僅是角色ID
注:inst_role.users獲取對象時,隱含了調用all()方法觸發執行,但如果像加一些過濾器(如排序),則需要在db.relationship中添加lazy='dynamic'關鍵字參數。然后即可引入過濾器:inst_role.users.order_by(Users.username)
4.2 多對多
Pending…
在Flask-SQLAlchemy中,刪除數據庫記錄,可映射至刪除代表該記錄的對象:
db.session.delete(mod_role) db.session.commit()
到此,關于“Flask如何使用SQLAlchemy實現持久化數據”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。