最近,我見到了很多針對 orm 的抨擊,但是我覺得有些批評是莫須有的。我本人就是 sqlalchemy 的忠實擁躉。在我的專案裡很多地方都用到了 sqlalchemy,我也為 sqlalchemy 專案貢獻了一些**。這篇文章裡,我會闡述你應當愛上 sqlalchemy 的10個理由。說實話,除了 sqlalchemy 以外還有很多優秀的 orm,我所闡述的大部分理由同樣適用於它們。但是 sqlalchemy 是我的最愛。
sqlalchemy 允許你使用 python **來定義資料庫模式(schema)。下面是乙個電子商務**的例子,乙個訂單就代表一條記錄。
class
orderitem
(base):
id = column
(integer, primary_key=true)
order = many_to_one('order')
product = many_to_one('product')
quantity = column
(integer)
定義資料庫模式的 python **在 sqlalchemy 中叫做模型(model)。因為這些模型都是用 python 的類實現的,所以你可以新增自己的類方法。這樣可以把相關功能放在一起,方便維護。
class
order
(base):
...def
update_stock
(self):
for item in self.items:
item.product.stock -= item.quantity
上面這個例子說明了,在 sqlalchemy 中資料庫的模式也可以通過版本控制來維護。所以使用sqlalchemy 的同時,你也可以享受到版本控制的諸多便利:比如版本追蹤、標籤、追溯(blame)等等。
alembic 是 sqlalchemy 的乙個資料庫管理外掛程式。當你修改模型的時候,alembic 可以自動更新資料庫模式。使用 alembic 來做一些新增表或者列的小改動是非常便捷快速的。
$ alembic upgrade head
info [alembic.context] context class postgresqlcontext.
info [alembic.context] will assume transactional ddl.
info [alembic.context] running upgrade none -> 1975ea83b712
儘管在開發環境中自動同步非常方便,但是大多數人還是想在生產環境中採用更穩妥一些的方式。這一點 alembic 也想到了,它可以自動生成修改的指令碼,資料庫管理員可以在檢視指令碼之後再應用到生產環境的資料庫上。
sqlalchemy 使用更 pythonic 的方式表示資料庫關係,這對於閱讀和編寫**來說是非常方便的。我們來看下面這個例子,這個例子可以列印出在乙個訂單中的所有產品。
for
item
in order.items:
print(item.product.name, item.quantity)
**非常的簡單易讀,但是打通了兩個資料庫,執行了 join 連線查詢。order.items 是一對多的關係,sqlalchemy 會自動載入 orderitem 中和這個訂單相關的物件。item.product 則儲存的是多對一的關係,sqlalchemy 會自動載入對應的產品。
sqlalchemy 也可以運用類。如果應用修改了乙個有對映的字段,物件會自動請求寫入資料庫。這個功能使編寫應用邏輯的時候沒有了後顧之憂。
類似用主鍵獲取物件這種簡單查詢只需要很少的**:
order = session.query(order).get(order_id)
使用 python 的查詢語法,我們可以實現更複雜的查詢。比如下面的例子,我要查詢兩天以前的有效訂單:
overdue_orders = session.query(order).filter(order.status == 'active'
&& order.time < datetime.now() - timedelta(days=2))
sqlalchemy 的語法可以讓你把 sql 語句和 python 的變數結合起來,並且可以杜絕 sql 注入攻擊。sqlalchemy 會在內部過載各種比較運算子,然後將它們轉換成 sql 語句。
當你執行一條非常複雜的查詢時,使用 sqlalchemy 語法來定義查詢也是可以的。但是我認為 sqlalchemy 可以勝任的查詢複雜程度是有限的,某些時候直接寫 sql 語句可能更容易些。在這種情況下,你可以定義資料庫檢視來完成複雜查詢,sqlalchemy 可以把檢視對映到 python 物件。
有些框架預設支援sqlalchemy ,比如說 pyramid。對於其他 web 框架,你需要安裝乙個整合庫來支援 sqlalchemy,比如說用於 flask 的 flask-sqlalchemy 或者用於 django 的 aldjemy。
sqlalchemy 會維持乙個連線池,為每乙個 web 請求提供乙個可用的資料庫連線。那些支援庫可以處理常見異常,提高應用的健壯性,讓應用在某些異常情況下不至於崩潰,比如執行時重啟資料庫這樣的操作。
每乙個請求都會用事務包裹起來,如果請求成功就提交事務,否則就回滾。這種設計使得外部方法能夠正確地與資料庫互動,而不需要關心具體的資料庫處理**。
大部分 orm 都使用的是延遲載入策略。在第一次呼叫關係時,一次 sql 查詢會執行,載入資料。像上面的例子,order.items 的呼叫實際上執行了一次 sql 查詢,之後的每次使用 item.product 都會發起另外的查詢。因為 item.product 是在乙個迴圈中呼叫的,所以會生成大量的 sql 查詢,導致效能降低。這種情況叫做「n+1 選擇問題」。
sqlalchemy 針對上述問題有乙個解決方案:預先載入(eager loading)。當我們第一次載入 order 這個物件時,我們可以通知 sqlalchemy 我們會使用那些關係,然後 sqlalchemy 就能在一次查詢中載入所有資料,語法如下所示:
session.query(order).options(joinedload_all('items.product')).get(order_id)
像 python 這樣的物件導向語言是鼓勵使用多型的。如果有乙個 person 的基類,我們就可以基於 person 來建立子類,比如 增加了新字段的employee 或者 customer 類。但是傳統的 sql 資料庫不支援多型,所以 orm 想要支援多型也是有心無力。
但是 sqlalchemy 在 sql 中完美地模擬了多型。我們在 python **中可以非常自然地使用多型,資料庫中的資料也可以通過 sql 便捷地獲取。在應用**中我們可以輕鬆地使用多型類,而不需要關心它們究竟是怎麼儲存的。
一些 orm 要求你的資料庫結構滿足既定條件,強制每張表都有單一主鍵列,甚至主鍵名稱必須是 「id」。如果你從頭建立乙個資料庫,這些限制並不是問題。但是如果你想用以前的資料庫,這些限制條件會阻止你訪問那些不滿足條件的表。
sqlalchemy 不會假定你的資料庫結構,所以可以完美支援以前的資料庫。還有乙個叫做 sqlacodegen 的工具可以根據已有的資料庫生成 sqlalchemy 模型。sqlalchemy 使得你可以通過簡單的 python 指令碼和以前的資料庫進行互動。
sqlalchemy 擁有清晰的分層架構。幾乎任何 sqlalchemy 庫都可以被重寫以滿足特定需求。
當在有多個使用者的雲應用上工作的時候,我發現了乙個非常有用的功能。比如說應用中大多數查詢都包含了過濾條件,只返回當前使用者的結果。就像下面這個例子:
products = session.query(product).filter(product.merchant == current_user.merchant).all()
但是我發現,如果一不小心忘記加過濾條件的話,可能讓某個使用者可以看到其他經銷商的資訊,而這是不允許的。謹慎起見,我們可以建立乙個自定義的 sqlalchemy 的 session 工廠函式,可以在會話中自動給所有查詢應用過濾條件。雖然只是這麼一點小小的控制**,卻可以讓你的應用安全係數更高。
有些開源專案的文件的確是漏洞百出,但是 sqlalchemy 不是這樣。sqlalchemy 的文件非常詳盡,並且還有從簡單例子到高階特性的學習指南,以及全面的 api 參考文件。這對於開發人員學習和使用 sqlalchemy 是非常有幫助的。
愛上未來的你
愛上未來的你 這個週末 如約的參加了本年度的cpa考試。由於是第三次參加這個考試了,再加上七年自考的經歷,所以考前的頭一天晚上再沒有了以前的那種激動和不安,甚至連應考的文具都是早上才準備的,差點把橡皮落在宿舍了。把手機鬧鈴設定到凌晨五點,但實際到五點半才起床。做完內務到六點半才出門,花十幾分鐘吃了兩...
程式設計師必定會愛上的10款軟體
第一款 truecrypt truecrypt可能很多人沒用過,它是乙個加密軟體,能夠對磁碟進行加密。還在擔心自己電腦中的重要檔案 私密檔案被人檢視。什麼,你以為把檔案設定了隱藏屬性別人就看不到了?快來用truecrypt 你必定會愛上它的。特點 對某一磁碟分割槽進行加密,開啟計算機後,如果你沒有開...
程式設計師必定會愛上的10款軟體
第一款 truecrypt truecrypt可能很多人沒用過,它是乙個加密軟體,能夠對磁碟進行加密。還在擔心自己電腦中的重要檔案 私密檔案被人檢視。什麼,你以為把檔案設定了隱藏屬性別人就看不到了?快來用truecrypt 你必定會愛上它的。特點 對某一磁碟分割槽進行加密,開啟計算機後,如果你沒有開...