開發入門
標準功能走不通、又確定不是設定問題時,再寫自訂模組(addon)。目標是:從空資料夾做出可安裝、可升級的最小模組。本頁只覆蓋最常用的 20%:清單檔、模型、檢視、權限。
先備:Python 基礎、會看 XML、Odoo 已用 Docker 跑起來(安裝)。想直接做一個完整可用的模組,請看 實作:圖書借閱模組;指令細節見 odoo-bin 指令。
模組骨架
把資料夾放進 addons(或 Compose 掛載的 extra-addons),名稱用英數與底線:
my_addon/
├─ __manifest__.py
├─ __init__.py
├─ models/
│ ├─ __init__.py
│ └─ my_model.py
├─ views/
│ └─ my_model_views.xml
└─ security/
└─ ir.model.access.csv
__manifest__.py 告訴 Odoo 這是什麼、依賴誰、要載入哪些檔:
{
"name": "My Addon",
"version": "18.0.1.0.0",
"author": "Your Name",
"license": "LGPL-3",
"depends": ["base"],
"data": [
"security/ir.model.access.csv",
"views/my_model_views.xml",
],
"installable": True,
}
版本號第一段與 Odoo 大版一致(18.0)。data 的順序有差:權限必須在檢視之前,否則一般使用者打不開選單。
模型與計算欄位
# models/my_model.py
from odoo import api, fields, models
class MyModel(models.Model):
_name = "my.model"
_description = "My Model"
name = fields.Char(required=True)
amount = fields.Float()
tax = fields.Float(compute="_compute_tax", store=True)
@api.depends("amount")
def _compute_tax(self):
for rec in self:
rec.tax = (rec.amount or 0.0) * 0.05
_name 是模型技術名稱,點號分隔。改欄位或模型後,必須升級模組(-u my_addon),資料庫結構才會更新。
檢視與選單
<odoo>
<record id="view_my_model_list" model="ir.ui.view">
<field name="name">my.model.list</field>
<field name="model">my.model</field>
<field name="arch" type="xml">
<list>
<field name="name"/>
<field name="amount"/>
<field name="tax"/>
</list>
</field>
</record>
<record id="view_my_model_form" model="ir.ui.view">
<field name="name">my.model.form</field>
<field name="model">my.model</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="amount"/>
<field name="tax" readonly="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_my_model" model="ir.actions.act_window">
<field name="name">My Models</field>
<field name="res_model">my.model</field>
<field name="view_mode">list,form</field>
</record>
<menuitem id="menu_my_root" name="My App"/>
<menuitem id="menu_my_model" name="My Models"
parent="menu_my_root" action="action_my_model"/>
</odoo>
tree 已改名為 list
Odoo 17 起清單檢視標籤是 <list>。舊文件的 <tree> 在新版可能仍相容一段時間,新模組請寫 list,view_mode 也用 list,form。
權限
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_my_model,my.model,model_my_model,base.group_user,1,1,1,1
沒有 ir.model.access.csv 列,一般使用者會看到「你沒有權限」。model_my_model 由 _name = my.model 自動對應(點改底線)。
安裝與升級
# 建立新模組骨架(也可以手動建資料夾)
docker compose run --rm odoo odoo scaffold my_addon /mnt/extra-addons
# 安裝、升級(--stop-after-init 表示做完就結束)
docker compose run --rm odoo odoo -d odoodb -i my_addon --stop-after-init
docker compose run --rm odoo odoo -d odoodb -u my_addon --stop-after-init
docker compose run 會用一個一次性容器執行,並由映像的入口程式自動帶上資料庫連線參數。若改用 docker compose exec 進入執行中的容器,要自己加 --db_host=db -r odoo -w odoo。原始碼安裝則把 odoo 換成 ./odoo-bin。
或在應用程式選單先「更新應用程式清單」再安裝。改 Python 欄位、XML 或 CSV 後都要升級;只改方法內的 Python 邏輯時重啟即可,加上 --dev=reload 甚至會自動重啟。各選項的完整說明見 odoo-bin 指令。
下一步
依序閱讀,每一頁都建立在前一頁之上:
- odoo-bin 指令:安裝、升級、shell、備份、翻譯,一次搞懂
- 實作:圖書借閱模組:關聯欄位、計算欄位、驗證、按鈕與狀態、群組權限
- 繼承與擴充:
_inherit、xpath檢視繼承、覆寫方法 - 測試與除錯:自動化測試、日誌、真實錯誤訊息速查
還沒涵蓋、知道去哪查即可:記錄規則(Record Rules)、QWeb 報表、Controller、Wizard、排程動作(Cron)。這些在官方開發者教學有完整練習,不必一次學完。
進一步學習
- Odoo 18 開發者文件
- 官方 Getting started 教學(從零做模組)
- ORM 參考
- OCA 程式規範(模組要給別人用時很有用)
- 影音教學 的開發相關資源