python ORM 框架 sqlalchemy
sqlalchemy 是一款Python語言寫的ORM框架, 該框架建立在資料庫API基礎之上。
sqlalchemy 本身無法操作資料庫,必須已第三方外掛為基礎,Dialect用於和資料API進行交流,根據不通的的配置呼叫不通的資料庫API,從而實現對資料庫的操作。
1 2 3 4 5 6 7 8 9 10 11 |
/ <dbname>
|
ORM
一、建立表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
sqlalchemy.ext.declarative import declarative_base
|
二、向資料庫新增資料
1 2 3 4 5 6 7 8 |
|
三、查詢
查詢的結果, 有幾種不同的型別, 這個需要注意, 像是:
- instance
- instance of list
- keyed tuple of list
- value of list
1、普通查詢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
2、多表查詢
1 2 3 4 5 |
|
3、條件查詢
1 2 3 4 5 6 7 8 9 |
|
4、函式
1 2 3 4 5 6 7 |
|
四、修改
兩種修改方式
1 2 3 4 5 6 |
|
如果涉及對屬性原值的引用, 則要考慮 synchronize_session
這個引數.
'evaluate'
預設值, 會同時修改當前 session 中的物件屬性.'fetch'
修改前, 會先通過select
查詢條目的值.‘False’
不修改當前 session 中的物件屬性.
在預設情況下, 因為會有修改當前會話中的物件屬性, 所以如果語句中有 SQL 函式, 或者"原值引用", 那是無法完成的操作, 自然也會報錯, 比如:
1 2 3 |
|
這種情況下, 就不能要求 SQLAlchemy 修改當前 session 的物件屬性了, 而是直接進行資料庫的互動, 不管當前會話值(將synchronize_session值設定為False):
1 |
|
是否修改當前會話的物件屬性, 涉及到當前會話的狀態. 如果當前會話過期, 那麼在獲取相關物件的屬性值時, SQLAlchemy 會自動作一次資料庫查詢, 以便獲取正確的值:
1 2 3 4 5 6 |
|
執行了 update
之後, 雖然相關物件的實際的屬性值已變更, 但是當前會話中的物件屬性值並沒有改變. 直到 session.commit()
之後, 當前會話變成"過期"狀態, 再次獲取 user.name
時, SQLAlchemy 通過 user
的 id
屬性, 重新去資料庫查詢了新值.
synchronize_session
設定成 'fetch'
不會有這樣的問題, 因為在做 update
時已經修改了當前會話中的物件了.
不管 synchronize_session
的行為如何, commit
之後 session
都會過期, 再次獲取相關物件值時, 都會重新作一次查詢.
好好體會上邊的話。
五、刪除
刪除同樣有像修改一樣的 synchronize_session
引數的問題, 影響當前會話的狀態.
1 2 3 4 |
|
六、join 操作
sqlalchemy 預設情況下的join 是內連線
1 2 3 |
|
四、外來鍵和關係
1、外來鍵的定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
新增資料
1 2 3 4 5 6 7 |
|
session.flush()
是進行資料庫互動, 但是事務並沒有提交. 進行資料庫互動之後, user.id
才有值.
定義了外來鍵, 對查詢來說, 並沒有影響. 外來鍵只是單純的一條約束而已. 當然, 可以在外來鍵上定義一些關聯的事件操作, 比如當外來鍵條目被刪除時, 欄位置成 null
, 或者關聯條目也被刪除等
獲取資料
1 2 3 |
|
對於 一對多 的關係, 使用 any()
函式查詢:
1 |
|
反之, 如果是 多對一 的關係, 則使用 has()
函式查詢:
1 |
|
上面的關係定義, 對應的屬性是實際查詢出的例項列表, 當條目數多的時候, 這樣可能會有問題. 比如使用者名稱下有成千上萬的文章, 一次全取出就太暴力了. 關係對應的屬性可以定義成一個 Query
1 2 3 4 5 6 7 |
|
這樣就能自由控制了
1 2 |
|
2、關係的表現形式
關係在物件屬性中的表現, 預設是列表, 但是, 這不是唯一的形式. 根據需要, 可以作成 dictionary , set 或者其它你需要的物件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
對於上面的兩個模型:
1 2 |
|
1 2 3 4 5 6 |
|
現在 user.blogs
是一個列表. 我們可以在 relationship()
呼叫時通過 collection_class
引數指定一個類, 來重新定義關係的表現形式:
set, 集合
1 2 3 |
|
attribute_mapped_collection , 字典, 鍵值從屬性取:
1 2 3 4 5 |
|
mapped_collection , 字典, 鍵值自定義:
1 2 3 4 5 |
|