本文為最好用的免費ERP系統(tǒng)Odoo 12開發(fā)手冊系列文章第五篇。
英文原著為Odoo 12 Development Essentials - Fourth Edition By Daniel Reis
?第一章 使用開發(fā)者模式快速入門 Odoo 12
?第二章 Odoo 12開發(fā)之開發(fā)環(huán)境準(zhǔn)備
?第三章 Odoo 12 開發(fā)之創(chuàng)建第一個 Odoo 應(yīng)用
?第四章 Odoo 12 開發(fā)之模塊繼承
?第五章 Odoo 12開發(fā)之導(dǎo)入、導(dǎo)出以及模塊數(shù)據(jù)
?第六章 Odoo 12開發(fā)之模型 - 結(jié)構(gòu)化應(yīng)用數(shù)據(jù)
?第七章 Odoo 12開發(fā)之記錄集 - 使用模型數(shù)據(jù)
?第八章 Odoo 12開發(fā)之業(yè)務(wù)邏輯 - 業(yè)務(wù)流程的支持
?第九章 Odoo 12開發(fā)之外部 API - 集成第三方系統(tǒng)
?第十章 Odoo 12開發(fā)之后臺視圖 - 設(shè)計用戶界面
?第十一章 Odoo 12開發(fā)之看板視圖和用戶端 QWeb
?第十二章 Odoo 12開發(fā)之報表和服務(wù)端 QWeb
?第十三章 Odoo 12開發(fā)之創(chuàng)建網(wǎng)站前端功能
?第十四章 Odoo 12開發(fā)之部署和維護(hù)生產(chǎn)實例
大多數(shù)Odoo 模塊的定義,如用戶界面和安全規(guī)則,實際是存儲在對應(yīng)數(shù)據(jù)表中的數(shù)據(jù)記錄。模塊中的 XML 和 CSV 文件不是 Odoo 應(yīng)用運行時使用,而是載入數(shù)據(jù)表的手段。正是因為這個原因,Odoo 模塊的一個重要部分是在文件中放入數(shù)據(jù)以在插件安裝時將其載入數(shù)據(jù)庫。
模塊可以包含初始數(shù)據(jù)和演示數(shù)據(jù),可通過數(shù)據(jù)文件將它們加入模塊。此外,了解 Odoo 數(shù)據(jù)的格式對于在項目實施上下文中導(dǎo)入導(dǎo)出業(yè)務(wù)數(shù)據(jù)也非常重要。
本文的主要內(nèi)容有:
- 理解外部標(biāo)識符的概念
- 導(dǎo)入導(dǎo)出數(shù)據(jù)文件
- 使用 CSV 文件
- 添加模塊數(shù)據(jù)
- 使用 XML 數(shù)據(jù)文件
開發(fā)準(zhǔn)備
本文要求讀者可以運行Odoo 服務(wù)并已安裝前面我們此前開發(fā)的圖書應(yīng)用。相關(guān)代碼請見GitHub 倉庫。你可能也同時安裝了第四章 Odoo 12 開發(fā)之模塊繼承中創(chuàng)建的library_member模塊,但本文并不要求使用該模型。
本文的更新后的代碼請見GitHub 倉庫。
理解外部標(biāo)識符的概念
外部標(biāo)識符,也稱為XML ID,是用于唯一標(biāo)識 Odoo 中特定記錄的有可讀性的字符串標(biāo)識符。在Odoo 中加載數(shù)據(jù)時它們就很重要了,這樣可以對已有數(shù)據(jù)記錄進(jìn)行修改或在其它數(shù)據(jù)記錄中引用它。
首先我們將討論外部標(biāo)識符的工作原理以及如何對其進(jìn)行檢查。然后我們會學(xué)習(xí)如何使用網(wǎng)頁客戶端來查找指定數(shù)據(jù)記錄的外部標(biāo)識符,在創(chuàng)建插件模塊或繼承已有模塊時需要經(jīng)常用到。
外部標(biāo)識符的工作原理
記錄在數(shù)據(jù)庫中的真實標(biāo)識符是自動分配的序列號,在安裝模塊時沒法預(yù)先知道將要分配的具體ID的。外部標(biāo)識符讓我們無需知道真實的數(shù)據(jù)庫 ID便可以引用一條相關(guān)記錄。XML ID 為數(shù)據(jù)庫 ID 提供了一個方便的別名,藉于此我們可以在任何時刻引用某一指定記錄。
Odoo 模塊數(shù)據(jù)文件中使用XML ID來定義記錄。其中一個原因是避免在升級模塊時創(chuàng)建重復(fù)的記錄,在升級時會再次將數(shù)據(jù)文件加載到數(shù)據(jù)庫中。我們要檢測已有記錄來進(jìn)行更新,而不是重復(fù)創(chuàng)建記錄。另一個原因是使用XML ID來支持交叉數(shù)據(jù):即需引用其它數(shù)據(jù)記錄的數(shù)據(jù)記錄。因為我們無法知道真實數(shù)據(jù)庫 ID,使用XML ID來由 Odoo 框架來進(jìn)行相應(yīng)的轉(zhuǎn)換。
Odoo 處理由外部標(biāo)識符向所分配的真實數(shù)據(jù)庫 ID 的轉(zhuǎn)換。背后的機(jī)制相當(dāng)簡單:Odoo 維護(hù)一張外部標(biāo)識符和對應(yīng)數(shù)據(jù)庫 ID 的映射表:ir.model.data model。
我們需啟用開發(fā)者模式才能訪問下文中的菜單。可通過在右上角頭像左側(cè)查看是否有調(diào)試圖標(biāo),如果沒有需在 Settings菜單頁啟用,具體方法可參照第一章 使用開發(fā)者模式快速入門 Odoo 12中的內(nèi)容。
通過菜單訪問Settings > Technical > Sequences & Identifiers > External Identifiers可查看已有映射。例如訪問外部標(biāo)識符列表并過濾出library_app模塊,將可以看到該模塊生成的外部標(biāo)識符:

可以看到外部標(biāo)識符有Complete ID標(biāo)簽。注意其組成部分為:模塊名+.+標(biāo)識符名,如library_app.action_library_book。
外部標(biāo)識符僅需在 Odoo 模塊內(nèi)唯一,兩個模塊中使用相同標(biāo)識符不會產(chǎn)生沖突。全局唯一標(biāo)識符是由模塊名和外部標(biāo)識符共同組成的,在上圖Complete ID項中可以看到。
在數(shù)據(jù)文件中使用外部標(biāo)識符,我們可以選擇完整的標(biāo)識符或僅外部標(biāo)識符部分。通常僅使用外部標(biāo)識符會更簡單,但使用完整標(biāo)識符時我們可以引用其它模塊中的數(shù)據(jù)記錄。做引用時不要忘記在模塊依賴中加入這些模塊以確保在我們的記錄之前加載這些記錄。
小貼士:有時即便引用相同模塊中的XML ID也需使用完整標(biāo)識符
在上圖列表最上方可以看到library_app.action_library_book完整標(biāo)識符。這是我們在模塊中創(chuàng)建的菜單操作,在相應(yīng)的菜單項中引用。點擊進(jìn)入表單視圖查看詳情。圖中可以看出library_app模塊中的action_library_book外部標(biāo)識符映射到ir.actions.act_window模型中的記錄 ID,此處為85:

除了作為其它應(yīng)用引用記錄的一種方式外,外部標(biāo)識符還可以避免重復(fù)導(dǎo)入帶來的重復(fù)數(shù)據(jù)。一旦外部標(biāo)識符已存在,則會在原有記錄上更新,避免了重復(fù)數(shù)據(jù)的新建。
查找外部標(biāo)識符
在為我們的模塊寫入數(shù)據(jù)記錄時,經(jīng)常需要查找已有外部標(biāo)識符來作引用。一種方式是訪問菜單Settings > Technical > Sequences & Identifiers > External Identifiers,前面已經(jīng)演示過。另一種方法是使用開發(fā)者菜單。在第一章 使用開發(fā)者模式快速入門 Odoo 12中介紹了如何激開發(fā)者模式。
要查找一個數(shù)據(jù)記錄的外部標(biāo)識符,我們應(yīng)打開對應(yīng)的表單視圖,在開發(fā)者菜單中選擇View Metadata選項。此時會顯示一個帶有記錄數(shù)據(jù)庫 ID 和外部標(biāo)識符(也稱作XML ID)的對話框。比如要查看 demo 用戶 ID,需通過 Settings > Users & Companies > Users 進(jìn)入用戶表單視圖,然后點擊開發(fā)者工具菜單中的View Metadata選項。此時可以看到XML ID是base.user_demo,數(shù)據(jù)庫 ID 是6:

查看表單、列表、搜索或 action 視圖中的外部標(biāo)識符,都可以使用開發(fā)者菜單。下面我們通過Edit View選項來打開相應(yīng)視圖的詳情表單。此時可以查看到External ID字段,其值即為外部標(biāo)識符。例如在下圖中,可以看到圖書表單視圖的External ID為library_app.view_form_book:

導(dǎo)入導(dǎo)出 CSV 數(shù)據(jù)文件
導(dǎo)出數(shù)據(jù)文件并查看文件結(jié)構(gòu)的簡易方式是使用內(nèi)置的導(dǎo)出功能。通過生成 CSV 文件,我們可以了解手動導(dǎo)入系統(tǒng)所需的格式,或編輯該文件批量導(dǎo)入,甚至是使用它生成我們插件模塊的演示數(shù)據(jù)。
下面我們一起來學(xué)習(xí)從 Odoo 用戶界面導(dǎo)入和導(dǎo)出的基礎(chǔ)知識。
導(dǎo)出數(shù)據(jù)
數(shù)據(jù)導(dǎo)出是表單視圖中的標(biāo)準(zhǔn)功能。要使用該功能, 需要勾選左側(cè)的復(fù)選框來選擇需導(dǎo)出的行,然后在上方的 Action 菜單中點擊 Export 選項。首先我們要在圖書應(yīng)用中添加一些帶有出版商和作者的圖書。下例中我使用此前添加的書籍。
我們還需要安裝 Contacts 應(yīng)用,這樣可以看到 Partner 的列表視圖,可從該處導(dǎo)出記錄。注意其默認(rèn)視圖為帶有名片的看板視圖,需要先切換為列表視圖:

可通過勾選列頭的篩選框來選擇所有匹配當(dāng)前搜索條件的記錄。
??Odoo 9中的修改
在 Odoo 更早的版本中,只有屏幕上顯示(當(dāng)頁)的記錄能被導(dǎo)出。Odoo 9做出了修改,勾選列頭的復(fù)選框可導(dǎo)出當(dāng)前過濾的所有匹配記錄,而不僅僅是當(dāng)前顯示。這對導(dǎo)出屏幕上無法展示全的大量記錄非常有用。
點擊 Export 選項進(jìn)入Export Data 對話表單,可選擇導(dǎo)出方式。我們比較關(guān)注的是導(dǎo)出方式可以讓我們通過手動或插件模塊來導(dǎo)入該文件:

在對話表單最上方,有兩個選項:
- What do you want do do?(老版本中為Export type),選擇Import-Compatible Export選項,這樣導(dǎo)出數(shù)據(jù)在以后導(dǎo)入時格式更友好。
- Export formats:可選擇CSV或Excel,我們將選擇 CSV 格式來更好理解原始導(dǎo)出格式,在很多表單應(yīng)用中都能被讀取。
下一步選取要導(dǎo)出的列,本例中簡化操作,僅選擇External ID和Name。如果我們點擊Export To File按鈕,就會下載帶有導(dǎo)出數(shù)據(jù)的文件。最終的 CSV 內(nèi)容類似:
"id","name"
"__export__.res_partner_45_5b73e404","Kaiwan N Billimoria"
"__export__.res_partner_42_49816b0d","Packt"
"__export__.res_partner_44_9e374a59","Russ McKendrick"
"__export__.res_partner_43_e38db1b7","Scott Gallagher"
補(bǔ)充:伸手黨請注意這里及后續(xù)的 ID 字段都與導(dǎo)出的系統(tǒng)有關(guān),不應(yīng)直接使用
第一行中包含列名,導(dǎo)入時會使用它們自動匹配目錄列。導(dǎo)出內(nèi)容有兩列:
- id:為每條記錄分配的外部 ID,如果不存在,會在模塊名處使用export 作為前綴自動生成一條新ID。
- name: 聯(lián)系人/Partner 名稱
帶有外部 ID 使我們可以編輯導(dǎo)出數(shù)據(jù)并重新導(dǎo)入來把修改更新到記錄中。
小貼士:由于會自動生成記錄 id,導(dǎo)出或?qū)牍δ芸捎糜谂烤庉?Odoo 數(shù)據(jù):將數(shù)據(jù)導(dǎo)出至 CSV,使用表單軟件批量編輯數(shù)據(jù),再導(dǎo)入 Odoo。
導(dǎo)入數(shù)據(jù)
首先應(yīng)確認(rèn)開啟了導(dǎo)入功能,默認(rèn)是開啟的。如果沒有,進(jìn)入Settings > General Settings,在 Users 版塊下勾選Import & Export選項即可。啟用該選項后,列表視圖上方 Create 按鈕旁就會顯示一個 Import按鈕。
注意:Import & Export 設(shè)置安裝base_import模塊,該模塊用于提供這一功能。
下面我們嘗試批量編輯Contact或Partner數(shù)據(jù)。使用電子表單或文本編輯器打開CSV并修改幾個值。將 id 欄留空即可新增行。前文已經(jīng)提到第一列 id 作為每行的唯一標(biāo)識符,這讓已有記錄可以被更新,而不會因重新導(dǎo)入數(shù)據(jù)重復(fù)創(chuàng)建。我們在導(dǎo)出表中編輯任意字段在導(dǎo)入時對應(yīng)記錄就會被更新。
對于要加入 CSV 文件的新行,我們可以自己添加外部標(biāo)識符或?qū)?id 列留空。兩種方式都會創(chuàng)建新的記錄。作為示例,我們添加一行id 留空、name 為Phillip K. Dick,來在數(shù)據(jù)庫中新建這一記錄。在 CSV文件中進(jìn)行保存,點擊 Import(Create 按鈕旁),然后點擊 Load File 按鈕選擇磁盤中 CSV 的路徑就出會出現(xiàn)如下導(dǎo)入助手:

點擊右上角的Test Import按鈕,檢查數(shù)據(jù)正確性。由于導(dǎo)入的文件是在 Odoo 中導(dǎo)出文件基礎(chǔ)上修改的,正常會有效并且各列會自動與數(shù)據(jù)庫中對應(yīng)字段匹配。因編輯所使用的軟件各異,有可能需對分隔符和編碼進(jìn)行處理。現(xiàn)在可以點擊 Import 按鈕,修改和新建記錄就會被載入到 Odoo 中。

CSV 數(shù)據(jù)文件中的關(guān)聯(lián)記錄
前面的示例非常簡單,一旦我們開使用關(guān)聯(lián)多張表的關(guān)聯(lián)字段時,數(shù)據(jù)文件就會變得更為復(fù)雜。我們處理過圖書中的 Partner 記錄,下面就看一下如何在圖書 CSV 文件中表示對這些 Partner 的引用。具體來說,有一個出版商(publisher_id字段)的many-to-one(或外鍵)關(guān)聯(lián),以及一個作者(author_ids字段)的many-to-many關(guān)聯(lián)。
CSV 文件的表頭行中關(guān)聯(lián)列應(yīng)在名稱后添加一個/id。它將使用外部標(biāo)識符來引用關(guān)聯(lián)記錄。本例中,我們將在publisher_id/id字段中加載圖書出版商,使用關(guān)聯(lián) Partner 的外部 ID 作為其值。
注意:可使用/.id來進(jìn)行替代來使用數(shù)據(jù)庫中的真實 ID(自動分配的數(shù)字 id),但極少使用到。除非有特別原因,否則請使用外部 ID 而非數(shù)據(jù)庫ID。同時要記住數(shù)據(jù)庫 ID 針對具體的數(shù)據(jù)庫,所以如果導(dǎo)入到非原始數(shù)據(jù)庫中這種操作大多數(shù)情況下都會失敗。
CSV 數(shù)據(jù)文件中也可導(dǎo)入many-to-many字段,這和添加帶雙引號并由逗號分隔的外部 ID 列表一樣簡單。例如,要載入圖書作者,將需要一個author_ids/id列,并使用一個關(guān)聯(lián) Partner外部 ID 的逗號分隔列表作為其值:
id, name, author_ids/id
book_docker, "Mastering Docker - Third Edition","__export__.res_partner_44_767f4606,__export__.res_partner_43_b97c9264"

One-to-many 字段通常是表頭和行或父子關(guān)系,對于這類關(guān)系有特別的支持方式:對于同一條父記錄可以有多個關(guān)聯(lián)行。此處我們在 Partner 模型中有一個 one-to-many字段的例子:公司可帶有多個聯(lián)系人。如果從 Partner 模型中導(dǎo)出數(shù)據(jù)并包含Contacts/Name 字段,就可以看到要導(dǎo)入此類型數(shù)據(jù)的格式(Contacts 中選擇Azure Interior:默認(rèn)應(yīng)為第一條,并執(zhí)行前述的導(dǎo)出步驟):
| id | name | child_ids/id | child_ids/name |
| base.res_partner_12 | Azure Interior | base.res_partner_address_15 | Brandon Freeman |
| | | base.res_partner_address_28 | Colleen Diaz |
| | | base.res_partner_address_16 | Nicole Ford |
Odoo 12 Partner 模型導(dǎo)出

id和 name 列為父記錄的,child_ids兩列為子記錄的。注意第一行記錄以下父記錄部分留空。上表中CSV 文件形式顯示為:
"id","name","child_ids/id","child_ids/name"
"base.res_partner_12","Azure Interior","base.res_partner_address_15","Brandon Freeman"
"","","base.res_partner_address_28","Colleen Diaz"
"","","base.res_partner_address_16","Nicole Ford"
可以看到id和name這兩列第一行有值,后兩行都為空。其中的父記錄為聯(lián)系人的公司信息。另兩行的前綴都是child_ids/并且在三行中都有數(shù)據(jù)。這些是父公司的聯(lián)系人信息。第一行包含公司和第一個聯(lián)系人,其余行僅包含聯(lián)系人這一子信息。
添加模塊數(shù)據(jù)
模塊使用數(shù)據(jù)文件來加載默認(rèn)數(shù)據(jù)、演示數(shù)據(jù)、用戶界面定義和其它需存入數(shù)據(jù)庫的配置??梢赃x擇使用 CSV 或 XML 文件。
??Odoo 12中的修改
Odoo 11及之前版本支持YAML格式文件,但在 Odoo 12移除了相關(guān)支持。相關(guān)使用示例可參考 Odoo 11官方模塊l10n_be,更多YAML格式相關(guān)信息,可訪問http://yaml.org/。
模塊所使用的 CSV 和我們前述使用導(dǎo)入功能時用的文件是一樣的。在模塊中使用這些文件時,文件名須與要導(dǎo)入數(shù)據(jù)的模型名一致。例如,導(dǎo)入library.book模型的 CSV 數(shù)據(jù)文件名應(yīng)為library.book.csv。CSV 數(shù)據(jù)文件經(jīng)常用作導(dǎo)入ir.model.access模型來獲取權(quán)限定義,通常放在security/子目錄下并命名為ir.model.access.csv。
演示數(shù)據(jù)
Odoo插件模塊可安裝演示數(shù)據(jù),推薦支持該安裝。為模塊提示使用示例和測試用的數(shù)據(jù)集會非常有用。模塊的演示數(shù)據(jù)通過manifest.py文件中的 demo 屬性來聲明。和 data 屬性一樣,后接一個包含模塊相對路徑的文件名列表。我們應(yīng)為library.book模塊添加一些演示數(shù)據(jù),一個簡易方式是從安裝了模塊的開發(fā)數(shù)據(jù)庫中導(dǎo)出數(shù)據(jù)。
按慣例數(shù)據(jù)文件放在data/子目錄下,應(yīng)以data/library.book.csv保存在library_app模塊下。因這個數(shù)據(jù)為模塊所有,應(yīng)在導(dǎo)出的數(shù)據(jù)中將標(biāo)識符的前綴export去除。
例如res.partner.csv文件可能長這樣:
id,name
res_partner_alexandre,"Alexandre Fayolle"
res_partner_daniel,"Daniel Reis"
res_partner_holger,"Holger Brunn"
res_partner_packt,"Packt Publishing"
那么圖書演示數(shù)據(jù)文件library.book.csv就應(yīng)該是這樣的:
"id","name","date_published","publisher_id/id","author_ids/id"
library_book_ode11,"Odoo Development Essentials 11","2018-03-01",res_partner_packt,res_partner_daniel
library_book_odc11,"Odoo 11 Development Cookbook","2018-01-01",res_partner_packt,"res_partner_alexandre,res_partner
_holger"
注意文件中同一條數(shù)據(jù)因顯示原因可能在不同行中,但實際是不能換行的。還應(yīng)記得在manifest.py的 demo 屬性中聲明數(shù)據(jù)文件:
'demo': [
'data/res.partner.csv',
'data/library.book.csv',
],
文件會以聲明的順序來加載,這個很重要,因為文件可能會因為未被安裝而無法引用其記錄。只要啟用了安裝演示數(shù)據(jù),下次更新時,這些內(nèi)容就會被導(dǎo)入。
??數(shù)據(jù)文件會在模塊升級時重新導(dǎo)入,但演示文件則并非如此,它們僅在安裝時導(dǎo)入。
當(dāng)然 XML 文件也可用于加載或初始化數(shù)據(jù),還可使用普通 CSV 文件所不具備的功能。
使用 XML 數(shù)據(jù)文件
CSV 文件是一種展示數(shù)據(jù)方便簡潔的格式,但 XML 文件更為強(qiáng)大,可在加載過程中提供更多的控制。比如,其文件名無需與所導(dǎo)入到的模型名稱一致。因為XML格式通過文件內(nèi)的XML元素可以提供更豐富的信息、更多的內(nèi)容。
在前面的文章中我們已經(jīng)使用過XML數(shù)據(jù)文件。視圖和菜單項這類用戶界面組件實際上都是存儲在系統(tǒng)模型中的記錄。模塊中的XML文件是將這些記錄加載到實例數(shù)據(jù)庫的方式。我們將在library_app模塊中添加一個數(shù)據(jù)文件data/book_demo.xml來作為展示,文件內(nèi)容如下:
<?xml version="1.0"?>
<odoo noupdate="1">
<!-- Data to load -->
<record model="res.partner" id="res_partner_huxley">
<field name="name">Aldous Huxley</field>
</record>
<record model="library.book" id="library_book_bnw">
<field name="name">Brave New World</field>
<field name="author_ids"
eval="[(4, ref('res_partner_huxley'))]" />
<field name="date_published">1932-01-01</field>
</record>
</odoo>
老規(guī)矩,新的數(shù)據(jù)文件應(yīng)在manifest.py中聲明:
'demo': [
...
'data/book_demo.xml',
],
類似 CSV 文件,該文件也會將數(shù)據(jù)加載到圖書模型中。

XML文件包含一個外層<odoo>元素,內(nèi)部可包含多個<record>元素與對應(yīng) CSV 數(shù)據(jù)行。
??數(shù)據(jù)文件中的外層<odoo>元素在9.0中才引入用于替換此前的<openerp>標(biāo)簽?,F(xiàn)在仍支持外層元素內(nèi)的<data>標(biāo)簽,為可選項。事實上現(xiàn)在<odoo>和<data>是等價的,我們可以在數(shù)據(jù)文件中使用任意一個作為外層元素。
<record>元素有兩個強(qiáng)制屬性: model 和作為記錄外部標(biāo)識符的 id,每個字段使用一個<field>標(biāo)簽來進(jìn)行寫入。注意此處字段名內(nèi)不可使用斜杠標(biāo)記,如不可使用<field name="publisher_id/id">。應(yīng)使用 ref 屬性來引用外部標(biāo)識符,一會兒就會討論到關(guān)聯(lián) to-many 字段。
你可能注意到在外層元素中使用了noupdate="1"屬性。這防止了在模塊升級時數(shù)據(jù)記錄的載入,不至于在后續(xù)編輯中丟失數(shù)據(jù)。
noupdate 數(shù)據(jù)屬性
升級模塊時,會重新加載數(shù)據(jù)并重寫模塊記錄。要謹(jǐn)記這可能意味著在升級模塊時會重寫任何對模塊數(shù)據(jù)的手動更改。
小貼士:值得注意的是,手動對視圖所做的自定義修改會在下一次模塊升級時丟失。避免這一問題正確的方法是創(chuàng)建繼承視圖來引入要做的修改。
這種重寫行為是默認(rèn)的,但可以修改有些數(shù)據(jù)僅在安裝時導(dǎo)入,后續(xù)模塊更新時則予以忽略,這正是通過<odoo>或<data>元素中的noupdate="1"來實現(xiàn)的。
這對于需初始化配置且預(yù)期需自定義的數(shù)據(jù)來說非常有用,因為這些手動修改在模塊更新時是安全的。例如在記錄訪問規(guī)則中經(jīng)常使用,可以適應(yīng)具體的實施需求。
在同一 XML 文件中可以有多個<data>版塊。可通過這個來分隔僅需導(dǎo)入一次的數(shù)據(jù)(noupdate="1")和需在每次更新時重新導(dǎo)入的數(shù)據(jù)(noupdate="0")。noupdate="0"是默認(rèn)值,所以可以省略不寫。注意還必須要有一個外層 XML 元素,就這個例子而言,使用兩個<data>標(biāo)簽,并在外層包裹一個<odoo>或<data>元素。
小貼士:noupdate屬性在開發(fā)模塊時可能會引起不適,因為會忽略后續(xù)修改。一個解決方案是,使用-i 參數(shù)重新安裝模塊而不是使用-u 參數(shù)進(jìn)行更新。命令行中使用-i 參數(shù)重新安裝會忽略數(shù)據(jù)記錄中的noupdate標(biāo)記。
noupdate標(biāo)記存儲在每條記錄的外部標(biāo)識符信息中??赏ㄟ^ Technical 菜單中的External Identifiers表單手動編輯,勾選Non Updatable 復(fù)選框即可。
??Odoo 12中的修改
點擊開發(fā)者菜單中的View Metadata時,現(xiàn)在在彈出的對話框中 XML ID 下面還會顯示No Update的值。并且在該處可通過點擊來修改該標(biāo)記的值。
在 XML 中定義記錄
在 XML 文件中,每個<record>元素有兩個基本屬性:id 和 model,并包含為對應(yīng)列設(shè)置的值。 id 屬性對應(yīng)記錄外部標(biāo)識符,model 對應(yīng)目標(biāo)模型。<field>元素有幾種分配值的方法,下面一起來看看。
直接為字段設(shè)置值
<field>元素的 name 屬性標(biāo)識要寫入的字段。寫入的值是元素內(nèi)容:字段開、閉標(biāo)簽之間的文本。對于 date 和datetime,帶有返回 date 或 datetime 對象表達(dá)式的 eval 屬性可進(jìn)行設(shè)置。返回的"YYYY-mm-dd"和"YYYY-mm-dd HH:MM:SS"字符串會進(jìn)行轉(zhuǎn)化。對于布爾字段,"0" and "False"都會轉(zhuǎn)換成 False,而任意非空值都會轉(zhuǎn)換成 True。
小貼士:Odoo 10中的修改
Odoo 10中改進(jìn)了從數(shù)據(jù)文件中讀取布爾值 False的方式。在老版本中,包含"0" and "False"在內(nèi)的非空值都會轉(zhuǎn)換成 True,直至 Odoo 9,布爾值仍需使用 eval 屬性進(jìn)行設(shè)置,如 eval="False"。
通過表達(dá)式設(shè)置值
設(shè)置字段值更復(fù)雜的方式是通過 eval 屬性,它會運行 Python 表達(dá)式并將結(jié)果分配給字段。表達(dá)式通過 Python 內(nèi)置的以及一些其它可創(chuàng)建表達(dá)式標(biāo)識符的上下文求值。
可使用如下 Python 模塊來處理日期:time, datetime, timedelta和relativedelta。通過它們可以計算日期值,在演示和測試數(shù)據(jù)經(jīng)常會用到,以讓日期和模塊安裝日期較近。關(guān)于 Python 模塊更多這類知識,請參考官方文檔。
比如,把值設(shè)為前一天,可使用如下代碼:
<field name="date_published"
eval="(datetime.now() + timedelta(-1))" />
求值上下文還可使用ref()函數(shù),用于將外部標(biāo)識符轉(zhuǎn)換為對應(yīng)的數(shù)據(jù)庫 ID。這可用于為關(guān)聯(lián)字段設(shè)置值。比如,可以使用它為publisher_id設(shè)置值:
<field name="publisher_id" eval="ref('res_partner_packt')" />
在 many-to-one 關(guān)聯(lián)字段上設(shè)置值
對于many-to-one關(guān)聯(lián)字段,要寫入的是關(guān)聯(lián)記錄的數(shù)據(jù)庫 ID。在 XML 文件中,我們一般會知道記錄的XML ID,然后就需要把它轉(zhuǎn)換成實際的數(shù)據(jù)庫 ID。
一種方式是像前文那樣使用帶有 ref()函數(shù)的 eval 屬性。更簡單的替代方式是使用在元素中可用的ref 屬性,使用它設(shè)置publisher_id many-to-one字段的值,我們可以這么寫:
<field name="publisher_id" ref="res_partner_packt" />
在 to-many 關(guān)聯(lián)字段上設(shè)置值
對于one-to-many和many-to-many字段,設(shè)置的不是單個 ID,而是一組關(guān)聯(lián) ID。并且還進(jìn)行幾種操作-我們可能需要將當(dāng)前的關(guān)聯(lián)記錄列表替換成另外一個,或為其添加幾次記錄,甚至是刪除其中的一些記錄。
要讓to-many字段支持寫操作,我們要在 eval 屬性中使用一種特殊的語法。我們使用一個元組組成的列表來寫入to-many字段。每個元組有三個元素,構(gòu)成一個寫入命令,根據(jù)第一個元素中的代碼進(jìn)行對應(yīng)操作。要重寫圖書作者列表,要使用如下代碼:
<field
name = "author_ids"
eval = "[(6, 0,
[ref('res_partner_alexandre'),
ref('res_partner_holger')]
)]"
/>
要往當(dāng)前圖書作者列表添加關(guān)聯(lián)記錄,需要添加如下代碼:
<field name="author_ids"
eval="[(4, ref('res_partner_daniel'))]"
/>
上述的例子非常常見。這里僅使用了一個命令,但在外層列中可以串聯(lián)多條命令。添加(4)和 替換(6)是最常用的命令。在進(jìn)行添加(4)時,不需要使用最后一個元素,因此在以上代碼中省略了。
完整的可用命令如下:
- (0, _ , {'field': value})新建一條記錄并將其與之關(guān)聯(lián)
- (1, id, {'field': value})更新已關(guān)聯(lián)記錄的值
- (2, id, _)移除關(guān)聯(lián)并刪除 id 關(guān)聯(lián)的記錄
- (3, id, _)移除關(guān)聯(lián)但不刪除 id 關(guān)聯(lián)的記錄。通常使用它來刪除many-to-many字段的關(guān)聯(lián)記錄
- (4, id, _)關(guān)聯(lián)已存在記錄,僅適用于many-to-many字段
- (5, _, _)刪除所有關(guān)聯(lián),但不刪除關(guān)聯(lián)記錄
- (6, _, [ids])替換已關(guān)聯(lián)記錄列表為此處的列表
上述下劃線_字符代表非關(guān)聯(lián)值,通常填入 o 或 False。
小貼士:后面的非關(guān)聯(lián)值可以放心地省略掉,如(4, id, _) 可使用(4, id)
常用模型的簡寫
如果回到第三章 Odoo 12 開發(fā)之創(chuàng)建第一個 Odoo 應(yīng)用,我們在 XML 中還發(fā)現(xiàn)<record>之外的元素,如<act_window>和<menuitem>。這些是常用模型的簡寫方式,是比常用的<record>更為簡練的符號。它們用于向 base 模型加載數(shù)據(jù)、組成用戶界面,在第十章 Odoo 12開發(fā)之后臺視圖 - 設(shè)計用戶界面會作更詳細(xì)的探討。
為便于查看,以下是可用的簡寫元素以及加載數(shù)據(jù)的對應(yīng)模型:
- <act_window>是窗口操作模型ir.actions.act_window
- <menuitem>是菜單項模型ir.ui.menu
- <report>是報表操作模型ir.actions.report.xml
- <template>是存儲在ir.ui.view模型中的 QWeb 模板
??Odoo 11中的修改
<url>標(biāo)簽已被淘汰并刪除。此前的版本中它用作為 URL 操作模型ir.actions.act_url加載記錄。
應(yīng)當(dāng)注意在用于修改已有記錄時,簡寫元素會覆蓋所有字段。這與僅寫入所提供字段的<record>基礎(chǔ)元素不同。因此在需修改用戶界面元素指定字段時,應(yīng)使用<record>元素。
XML 文件中的其它操作
截至目前我們了解了如何使用 XML 文件添加和更新數(shù)據(jù)。但也可以通過 XML 文件刪除數(shù)據(jù)以及執(zhí)行指定模型方法。對更復(fù)雜的數(shù)據(jù)場景會非常有用。
刪除記錄
我們可以使用<delete>元素刪除數(shù)據(jù)記錄,使用 ID 或搜索域來定位要刪除的記錄。例如,使用搜索域查找記錄并刪除:
<delete
model="res.partner"
search="[('id','=',ref('library_app.res_partner_daniel'))]"
/>
如果知道要刪除記錄的具體 ID,可使用 id 屬性。上例還可以寫成這樣:
<delete model="res.partner" id="library_app.res_partner_daniel" />
調(diào)用模型方法
XML 文件還可以通過<function>元素在加載過程中執(zhí)行任意方法,可用于設(shè)定演示和測試數(shù)據(jù)。比如 Odoo 捆綁的 Notes 應(yīng)用,使用它來設(shè)定演示數(shù)據(jù):
<data noupdate="1">
<function
model="res.users"
name="_init_data_user_note_stages"
eval="[]" />
</data>
這會調(diào)用res.users模型中的_init_data_user_note_stages方法,不傳任何參數(shù)。由參數(shù)列表eval傳遞,此處為空列表。
總結(jié)
本文中我們學(xué)習(xí)了如何在文件文中展示數(shù)據(jù)??捎米魇謩酉?Odoo 導(dǎo)入數(shù)據(jù),或放在插件模塊中作為默認(rèn)或演示數(shù)據(jù)。通過學(xué)習(xí)我們可以通過網(wǎng)頁界面導(dǎo)出并導(dǎo)入 CSV 數(shù)據(jù)文件了,以及通過外部 ID 來檢測并更新數(shù)據(jù)庫中已有的記錄。也可用作批量編輯數(shù)據(jù),只需編輯導(dǎo)出的 CSV 文件再重新導(dǎo)入即可。
我們還詳細(xì)學(xué)習(xí)了 XML 數(shù)據(jù)文件的結(jié)構(gòu)以及所提供功能。不僅可以為字段設(shè)置值,還可以執(zhí)行刪除記錄和調(diào)用方法一類的操作。
下一篇文章中,我們將集中學(xué)習(xí)如何使用記錄來與模型中所含數(shù)據(jù)協(xié)作。這些工具可供我們實現(xiàn)應(yīng)用的業(yè)務(wù)邏輯和規(guī)則。
???第六章 Odoo 12開發(fā)之模型 - 結(jié)構(gòu)化應(yīng)用數(shù)據(jù)
學(xué)霸專區(qū)
- XML ID 與外部 ID 的區(qū)別是什么?
- 插件模塊中可使用什么類型的數(shù)據(jù)文件?
- 以下 XML 片段有什么問題?
<field name="user_id">[(4, 0, [ref(base.user_demo)])]</field>
- 一個插件模塊中的數(shù)據(jù)文件是否可以覆蓋另一個模塊中創(chuàng)建的記錄?
- 插件模塊升級時,是否所有數(shù)據(jù)記錄都會被重寫為模塊默認(rèn)值?
擴(kuò)展閱讀
Odoo 官方文檔中提供了有關(guān)數(shù)據(jù)文件的更多資料。
本文首發(fā)地址:Alan Hou的個人博客