ORM 是什麼?在 Odoo 又代表什麼?

了解 Odoo 的 ORM 框架

Andy Cheng
ORM 是什麼?在 Odoo 又代表什麼?

ORM

在剛開始學習如何客製化 Odoo 時,最常碰到的障礙之一,就是 Odoo 的 ORM 框架。 ORM 框架的用意在於,分離程式與資料庫,讓寫程式的人可以不必擔心資料庫的資料結構,專注在程式邏輯上。但對於習慣直接存取資料庫的程式設計師來說,這樣的概念在一開始可能難以接受,需要花些時間才能理解。

這裡就來告訴大家,什麼是 ORM ,以及 Odoo 是如何呈現 ORM 的。

什麼是 ORM ?

ORM 是 Oject-Relational Mapping 的縮寫,中文可以翻譯為「物件關係映射」,是一種程式上的概念和技術。一般使用,大多是為了分離資料庫邏輯和程式邏輯,減少多人共同作業的難度,以及後續維護的難度。其它常見使用 ORM 的例子像是, Python 常見的框架 Django ,或是 SQLAlchemy

使用 ORM 的框架時,框架會將資料庫的資料轉換成物件的形式,供開發人員使用。開發人員不需要煩心資料在資料庫內的欄位設定,而是可以以程式語言原生的方式對物件作操作,框架會自動處理與資料庫溝通的部分。

初學 ORM 的第一件事,就是要先忘記資料庫這件事。但是用了 ORM ,不代表以後都不需要直接處理資料庫。 ORM 有其優點,但相對也會有效能問題和使用限制。當需要操作大量資料,或是有執行時間上的限制時,直接處理資料庫還是有其必要性。

ORM 的詳細概念解釋可以參照維基百科的說明

物件關係映射 - 維基百科

Odoo 的 ORM

Odoo 的 ORM 框架,官方稱之為 Odoo ORM API (可參見官方文件),是資料庫的資料表,與 model 間的轉換。資料表內的資料,則轉換成 model 的 recordset (資料集)。 Odoo 的 recordset 是屬於 Python 的 iterable (可迭代物) ,所以可以使用許多類似於 list (列表)的函式。例如:

recordset.filtered(lambda r: r.name is not False)

就近似於 Python 原生的 filter 函式。 recordset 也可使用在 for 迴圈中:

for r in recordset:
print(r.name)

這裡也可以注意到,存取資料的時候,是以存取物件屬性的方式( r.xxx ),而不是 dictionary (字典)的方式( r['xxx'] )。

Odoo recordset operation

定義資料結構

Odoo 的資料結構稱為 model ,概念類似於物件導向中的 class (類別)。 Model 中定義了欄位( field ),概念類似於 class 的 property (屬性),例如:

name = fields.Char(string='Name', required=True)

就定義了一個叫做 name 的欄位,欄位的標籤( label )是 Name ,且為必填欄位。

而:

value = fields.Float(string='Value', digits=(2, 4))

則定義了一個精度到小數下四位,四捨五入到小數下二位的浮點數欄位。

Odoo Model fields

ORM 要點

使用 Odoo 的 ORM 的時候,建議記得以下要點:

  1. 忘記資料庫這件事,放心讓 Odoo 處理。

  2. 妥善規劃資料結構,許多規劃資料表結構的規則,依然適用在規劃 model 上。雖然 Odoo 會替你處理存取資料庫的苦工,但是妥善規劃的資料結構可以讓 Odoo 事半功倍。

  3. 不必強迫什麼都一定透過 Odoo ORM 處理。 ORM 有其優缺點,不適合的情況下, ORM 反而事倍功半。

Odoo ORM 不是萬能,但是學好它,可以讓你在極短的時間內,就客製化出你想要的功能。

Odoo model methods