本文為最好用的免費(fèi)ERP系統(tǒng)Odoo 12開發(fā)手冊(cè)系列文章第五篇候齿。
英文原著為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)建第一個(gè) 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ā)之后臺(tái)視圖 - 設(shè)計(jì)用戶界面
?第十一章 Odoo 12開發(fā)之看板視圖和用戶端 QWeb
?第十二章 Odoo 12開發(fā)之報(bào)表和服務(wù)端 QWeb
?第十三章 Odoo 12開發(fā)之創(chuàng)建網(wǎng)站前端功能
?第十四章 Odoo 12開發(fā)之部署和維護(hù)生產(chǎn)實(shí)例
大多數(shù)Odoo 模塊的定義肌幽,如用戶界面和安全規(guī)則,實(shí)際是存儲(chǔ)在對(duì)應(yīng)數(shù)據(jù)表中的數(shù)據(jù)記錄糯耍。模塊中的 XML 和 CSV 文件不是 Odoo 應(yīng)用運(yùn)行時(shí)使用扔字,而是載入數(shù)據(jù)表的手段。正是因?yàn)檫@個(gè)原因温技,Odoo 模塊的一個(gè)重要部分是在文件中放入數(shù)據(jù)以在插件安裝時(shí)將其載入數(shù)據(jù)庫(kù)革为。
模塊可以包含初始數(shù)據(jù)和演示數(shù)據(jù),可通過數(shù)據(jù)文件將它們加入模塊舵鳞。此外震檩,了解 Odoo 數(shù)據(jù)的格式對(duì)于在項(xiàng)目實(shí)施上下文中導(dǎo)入導(dǎo)出業(yè)務(wù)數(shù)據(jù)也非常重要。
本文的主要內(nèi)容有:
- 理解外部標(biāo)識(shí)符的概念
- 導(dǎo)入導(dǎo)出數(shù)據(jù)文件
- 使用 CSV 文件
- 添加模塊數(shù)據(jù)
- 使用 XML 數(shù)據(jù)文件
開發(fā)準(zhǔn)備
本文要求讀者可以運(yùn)行Odoo 服務(wù)并已安裝前面我們此前開發(fā)的圖書應(yīng)用蜓堕。相關(guān)代碼請(qǐng)見GitHub 倉(cāng)庫(kù)抛虏。你可能也同時(shí)安裝了第四章 Odoo 12 開發(fā)之模塊繼承中創(chuàng)建的library_member模塊,但本文并不要求使用該模型套才。
本文的更新后的代碼請(qǐng)見GitHub 倉(cāng)庫(kù)迂猴。
理解外部標(biāo)識(shí)符的概念
外部標(biāo)識(shí)符,也稱為XML ID背伴,是用于唯一標(biāo)識(shí) Odoo 中特定記錄的有可讀性的字符串標(biāo)識(shí)符沸毁。在Odoo 中加載數(shù)據(jù)時(shí)它們就很重要了,這樣可以對(duì)已有數(shù)據(jù)記錄進(jìn)行修改或在其它數(shù)據(jù)記錄中引用它傻寂。
首先我們將討論外部標(biāo)識(shí)符的工作原理以及如何對(duì)其進(jìn)行檢查息尺。然后我們會(huì)學(xué)習(xí)如何使用網(wǎng)頁(yè)客戶端來查找指定數(shù)據(jù)記錄的外部標(biāo)識(shí)符,在創(chuàng)建插件模塊或繼承已有模塊時(shí)需要經(jīng)常用到崎逃。
外部標(biāo)識(shí)符的工作原理
記錄在數(shù)據(jù)庫(kù)中的真實(shí)標(biāo)識(shí)符是自動(dòng)分配的序列號(hào)掷倔,在安裝模塊時(shí)沒法預(yù)先知道將要分配的具體ID的。外部標(biāo)識(shí)符讓我們無需知道真實(shí)的數(shù)據(jù)庫(kù) ID便可以引用一條相關(guān)記錄个绍。XML ID 為數(shù)據(jù)庫(kù) ID 提供了一個(gè)方便的別名勒葱,藉于此我們可以在任何時(shí)刻引用某一指定記錄。
Odoo 模塊數(shù)據(jù)文件中使用XML ID來定義記錄巴柿。其中一個(gè)原因是避免在升級(jí)模塊時(shí)創(chuàng)建重復(fù)的記錄凛虽,在升級(jí)時(shí)會(huì)再次將數(shù)據(jù)文件加載到數(shù)據(jù)庫(kù)中。我們要檢測(cè)已有記錄來進(jìn)行更新广恢,而不是重復(fù)創(chuàng)建記錄凯旋。另一個(gè)原因是使用XML ID來支持交叉數(shù)據(jù):即需引用其它數(shù)據(jù)記錄的數(shù)據(jù)記錄。因?yàn)槲覀儫o法知道真實(shí)數(shù)據(jù)庫(kù) ID,使用XML ID來由 Odoo 框架來進(jìn)行相應(yīng)的轉(zhuǎn)換至非。
Odoo 處理由外部標(biāo)識(shí)符向所分配的真實(shí)數(shù)據(jù)庫(kù) ID 的轉(zhuǎn)換钠署。背后的機(jī)制相當(dāng)簡(jiǎn)單:Odoo 維護(hù)一張外部標(biāo)識(shí)符和對(duì)應(yīng)數(shù)據(jù)庫(kù) ID 的映射表:ir.model.data model。
我們需啟用開發(fā)者模式才能訪問下文中的菜單荒椭⌒扯Γ可通過在右上角頭像左側(cè)查看是否有調(diào)試圖標(biāo),如果沒有需在 Settings菜單頁(yè)啟用趣惠,具體方法可參照第一章 使用開發(fā)者模式快速入門 Odoo 12中的內(nèi)容狸棍。
通過菜單訪問Settings > Technical > Sequences & Identifiers > External Identifiers可查看已有映射。例如訪問外部標(biāo)識(shí)符列表并過濾出library_app模塊味悄,將可以看到該模塊生成的外部標(biāo)識(shí)符:
可以看到外部標(biāo)識(shí)符有Complete ID標(biāo)簽草戈。注意其組成部分為:模塊名+.+標(biāo)識(shí)符名,如library_app.action_library_book侍瑟。
外部標(biāo)識(shí)符僅需在 Odoo 模塊內(nèi)唯一唐片,兩個(gè)模塊中使用相同標(biāo)識(shí)符不會(huì)產(chǎn)生沖突。全局唯一標(biāo)識(shí)符是由模塊名和外部標(biāo)識(shí)符共同組成的丢习,在上圖Complete ID項(xiàng)中可以看到牵触。
在數(shù)據(jù)文件中使用外部標(biāo)識(shí)符淮悼,我們可以選擇完整的標(biāo)識(shí)符或僅外部標(biāo)識(shí)符部分咐低。通常僅使用外部標(biāo)識(shí)符會(huì)更簡(jiǎn)單,但使用完整標(biāo)識(shí)符時(shí)我們可以引用其它模塊中的數(shù)據(jù)記錄袜腥。做引用時(shí)不要忘記在模塊依賴中加入這些模塊以確保在我們的記錄之前加載這些記錄见擦。
小貼士:有時(shí)即便引用相同模塊中的XML ID也需使用完整標(biāo)識(shí)符
在上圖列表最上方可以看到library_app.action_library_book完整標(biāo)識(shí)符。這是我們?cè)谀K中創(chuàng)建的菜單操作羹令,在相應(yīng)的菜單項(xiàng)中引用鲤屡。點(diǎn)擊進(jìn)入表單視圖查看詳情。圖中可以看出library_app模塊中的action_library_book外部標(biāo)識(shí)符映射到ir.actions.act_window模型中的記錄 ID福侈,此處為85:
除了作為其它應(yīng)用引用記錄的一種方式外酒来,外部標(biāo)識(shí)符還可以避免重復(fù)導(dǎo)入帶來的重復(fù)數(shù)據(jù)。一旦外部標(biāo)識(shí)符已存在肪凛,則會(huì)在原有記錄上更新堰汉,避免了重復(fù)數(shù)據(jù)的新建。
查找外部標(biāo)識(shí)符
在為我們的模塊寫入數(shù)據(jù)記錄時(shí)伟墙,經(jīng)常需要查找已有外部標(biāo)識(shí)符來作引用翘鸭。一種方式是訪問菜單Settings > Technical > Sequences & Identifiers > External Identifiers,前面已經(jīng)演示過戳葵。另一種方法是使用開發(fā)者菜單就乓。在第一章 使用開發(fā)者模式快速入門 Odoo 12中介紹了如何激開發(fā)者模式。
要查找一個(gè)數(shù)據(jù)記錄的外部標(biāo)識(shí)符,我們應(yīng)打開對(duì)應(yīng)的表單視圖生蚁,在開發(fā)者菜單中選擇View Metadata選項(xiàng)噩翠。此時(shí)會(huì)顯示一個(gè)帶有記錄數(shù)據(jù)庫(kù) ID 和外部標(biāo)識(shí)符(也稱作XML ID)的對(duì)話框。比如要查看 demo 用戶 ID邦投,需通過 Settings > Users & Companies > Users 進(jìn)入用戶表單視圖绎秒,然后點(diǎn)擊開發(fā)者工具菜單中的View Metadata選項(xiàng)。此時(shí)可以看到XML ID是base.user_demo尼摹,數(shù)據(jù)庫(kù) ID 是6:
查看表單见芹、列表、搜索或 action 視圖中的外部標(biāo)識(shí)符蠢涝,都可以使用開發(fā)者菜單玄呛。下面我們通過Edit View選項(xiàng)來打開相應(yīng)視圖的詳情表單。此時(shí)可以查看到External ID字段和二,其值即為外部標(biāo)識(shí)符徘铝。例如在下圖中,可以看到圖書表單視圖的External ID為library_app.view_form_book:
導(dǎo)入導(dǎo)出 CSV 數(shù)據(jù)文件
導(dǎo)出數(shù)據(jù)文件并查看文件結(jié)構(gòu)的簡(jiǎn)易方式是使用內(nèi)置的導(dǎo)出功能惯吕。通過生成 CSV 文件惕它,我們可以了解手動(dòng)導(dǎo)入系統(tǒng)所需的格式,或編輯該文件批量導(dǎo)入废登,甚至是使用它生成我們插件模塊的演示數(shù)據(jù)淹魄。
下面我們一起來學(xué)習(xí)從 Odoo 用戶界面導(dǎo)入和導(dǎo)出的基礎(chǔ)知識(shí)。
導(dǎo)出數(shù)據(jù)
數(shù)據(jù)導(dǎo)出是表單視圖中的標(biāo)準(zhǔn)功能堡距。要使用該功能甲锡, 需要勾選左側(cè)的復(fù)選框來選擇需導(dǎo)出的行,然后在上方的 Action 菜單中點(diǎn)擊 Export 選項(xiàng)羽戒。首先我們要在圖書應(yīng)用中添加一些帶有出版商和作者的圖書缤沦。下例中我使用此前添加的書籍。
我們還需要安裝 Contacts 應(yīng)用易稠,這樣可以看到 Partner 的列表視圖缸废,可從該處導(dǎo)出記錄。注意其默認(rèn)視圖為帶有名片的看板視圖驶社,需要先切換為列表視圖:
可通過勾選列頭的篩選框來選擇所有匹配當(dāng)前搜索條件的記錄企量。
??Odoo 9中的修改
在 Odoo 更早的版本中行贪,只有屏幕上顯示(當(dāng)頁(yè))的記錄能被導(dǎo)出愕难。Odoo 9做出了修改趾痘,勾選列頭的復(fù)選框可導(dǎo)出當(dāng)前過濾的所有匹配記錄淀歇,而不僅僅是當(dāng)前顯示蓄氧。這對(duì)導(dǎo)出屏幕上無法展示全的大量記錄非常有用南誊。
點(diǎn)擊 Export 選項(xiàng)進(jìn)入Export Data 對(duì)話表單咒唆,可選擇導(dǎo)出方式硼补。我們比較關(guān)注的是導(dǎo)出方式可以讓我們通過手動(dòng)或插件模塊來導(dǎo)入該文件:
在對(duì)話表單最上方,有兩個(gè)選項(xiàng):
- What do you want do do?(老版本中為Export type)拇勃,選擇Import-Compatible Export選項(xiàng)四苇,這樣導(dǎo)出數(shù)據(jù)在以后導(dǎo)入時(shí)格式更友好。
- Export formats:可選擇CSV或Excel方咆,我們將選擇 CSV 格式來更好理解原始導(dǎo)出格式月腋,在很多表單應(yīng)用中都能被讀取。
下一步選取要導(dǎo)出的列瓣赂,本例中簡(jiǎn)化操作榆骚,僅選擇External ID和Name。如果我們點(diǎn)擊Export To File按鈕煌集,就會(huì)下載帶有導(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ǔ)充:伸手黨請(qǐng)注意這里及后續(xù)的 ID 字段都與導(dǎo)出的系統(tǒng)有關(guān),不應(yīng)直接使用
第一行中包含列名苫纤,導(dǎo)入時(shí)會(huì)使用它們自動(dòng)匹配目錄列碉钠。導(dǎo)出內(nèi)容有兩列:
- id:為每條記錄分配的外部 ID,如果不存在卷拘,會(huì)在模塊名處使用export 作為前綴自動(dòng)生成一條新ID喊废。
- name: 聯(lián)系人/Partner 名稱
帶有外部 ID 使我們可以編輯導(dǎo)出數(shù)據(jù)并重新導(dǎo)入來把修改更新到記錄中。
小貼士:由于會(huì)自動(dòng)生成記錄 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選項(xiàng)即可遍搞。啟用該選項(xiàng)后罗侯,列表視圖上方 Create 按鈕旁就會(huì)顯示一個(gè) Import按鈕。
注意:Import & Export 設(shè)置安裝base_import模塊溪猿,該模塊用于提供這一功能钩杰。
下面我們嘗試批量編輯Contact或Partner數(shù)據(jù)。使用電子表單或文本編輯器打開CSV并修改幾個(gè)值诊县。將 id 欄留空即可新增行讲弄。前文已經(jīng)提到第一列 id 作為每行的唯一標(biāo)識(shí)符,這讓已有記錄可以被更新依痊,而不會(huì)因重新導(dǎo)入數(shù)據(jù)重復(fù)創(chuàng)建避除。我們?cè)趯?dǎo)出表中編輯任意字段在導(dǎo)入時(shí)對(duì)應(yīng)記錄就會(huì)被更新怎披。
對(duì)于要加入 CSV 文件的新行,我們可以自己添加外部標(biāo)識(shí)符或?qū)?id 列留空瓶摆。兩種方式都會(huì)創(chuàng)建新的記錄凉逛。作為示例,我們添加一行id 留空群井、name 為Phillip K. Dick状飞,來在數(shù)據(jù)庫(kù)中新建這一記錄。在 CSV文件中進(jìn)行保存书斜,點(diǎn)擊 Import(Create 按鈕旁)诬辈,然后點(diǎn)擊 Load File 按鈕選擇磁盤中 CSV 的路徑就出會(huì)出現(xiàn)如下導(dǎo)入助手:
點(diǎn)擊右上角的Test Import按鈕,檢查數(shù)據(jù)正確性荐吉。由于導(dǎo)入的文件是在 Odoo 中導(dǎo)出文件基礎(chǔ)上修改的自晰,正常會(huì)有效并且各列會(huì)自動(dòng)與數(shù)據(jù)庫(kù)中對(duì)應(yīng)字段匹配。因編輯所使用的軟件各異稍坯,有可能需對(duì)分隔符和編碼進(jìn)行處理〕贶瘢現(xiàn)在可以點(diǎn)擊 Import 按鈕,修改和新建記錄就會(huì)被載入到 Odoo 中瞧哟。
CSV 數(shù)據(jù)文件中的關(guān)聯(lián)記錄
前面的示例非常簡(jiǎn)單混巧,一旦我們開使用關(guān)聯(lián)多張表的關(guān)聯(lián)字段時(shí),數(shù)據(jù)文件就會(huì)變得更為復(fù)雜勤揩。我們處理過圖書中的 Partner 記錄咧党,下面就看一下如何在圖書 CSV 文件中表示對(duì)這些 Partner 的引用。具體來說陨亡,有一個(gè)出版商(publisher_id字段)的many-to-one(或外鍵)關(guān)聯(lián)傍衡,以及一個(gè)作者(author_ids字段)的many-to-many關(guān)聯(lián)。
CSV 文件的表頭行中關(guān)聯(lián)列應(yīng)在名稱后添加一個(gè)/id负蠕。它將使用外部標(biāo)識(shí)符來引用關(guān)聯(lián)記錄蛙埂。本例中,我們將在publisher_id/id字段中加載圖書出版商遮糖,使用關(guān)聯(lián) Partner 的外部 ID 作為其值绣的。
注意:可使用/.id來進(jìn)行替代來使用數(shù)據(jù)庫(kù)中的真實(shí) ID(自動(dòng)分配的數(shù)字 id),但極少使用到欲账。除非有特別原因屡江,否則請(qǐng)使用外部 ID 而非數(shù)據(jù)庫(kù)ID。同時(shí)要記住數(shù)據(jù)庫(kù) ID 針對(duì)具體的數(shù)據(jù)庫(kù)赛不,所以如果導(dǎo)入到非原始數(shù)據(jù)庫(kù)中這種操作大多數(shù)情況下都會(huì)失敗惩嘉。
CSV 數(shù)據(jù)文件中也可導(dǎo)入many-to-many字段,這和添加帶雙引號(hào)并由逗號(hào)分隔的外部 ID 列表一樣簡(jiǎn)單踢故。例如文黎,要載入圖書作者奏路,將需要一個(gè)author_ids/id列,并使用一個(gè)關(guān)聯(lián) Partner外部 ID 的逗號(hào)分隔列表作為其值:
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)系臊诊,對(duì)于這類關(guān)系有特別的支持方式:對(duì)于同一條父記錄可以有多個(gè)關(guān)聯(lián)行鸽粉。此處我們?cè)?Partner 模型中有一個(gè) one-to-many字段的例子:公司可帶有多個(gè)聯(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)系人信息位他。第一行包含公司和第一個(gè)聯(lián)系人氛濒,其余行僅包含聯(lián)系人這一子信息。
添加模塊數(shù)據(jù)
模塊使用數(shù)據(jù)文件來加載默認(rèn)數(shù)據(jù)鹅髓、演示數(shù)據(jù)舞竿、用戶界面定義和其它需存入數(shù)據(jù)庫(kù)的配置×耄可以選擇使用 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)入功能時(shí)用的文件是一樣的仰挣。在模塊中使用這些文件時(shí),文件名須與要導(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ù)漱竖,推薦支持該安裝禽篱。為模塊提示使用示例和測(cè)試用的數(shù)據(jù)集會(huì)非常有用。模塊的演示數(shù)據(jù)通過manifest.py文件中的 demo 屬性來聲明馍惹。和 data 屬性一樣躺率,后接一個(gè)包含模塊相對(duì)路徑的文件名列表玛界。我們應(yīng)為library.book模塊添加一些演示數(shù)據(jù),一個(gè)簡(jiǎn)易方式是從安裝了模塊的開發(fā)數(shù)據(jù)庫(kù)中導(dǎo)出數(shù)據(jù)悼吱。
按慣例數(shù)據(jù)文件放在data/子目錄下慎框,應(yīng)以data/library.book.csv保存在library_app模塊下。因這個(gè)數(shù)據(jù)為模塊所有后添,應(yīng)在導(dǎo)出的數(shù)據(jù)中將標(biāo)識(shí)符的前綴export去除笨枯。
例如res.partner.csv文件可能長(zhǎng)這樣:
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ù)因顯示原因可能在不同行中,但實(shí)際是不能換行的遇西。還應(yīng)記得在manifest.py的 demo 屬性中聲明數(shù)據(jù)文件:
'demo': [
'data/res.partner.csv',
'data/library.book.csv',
],
文件會(huì)以聲明的順序來加載馅精,這個(gè)很重要,因?yàn)槲募赡軙?huì)因?yàn)槲幢话惭b而無法引用其記錄粱檀。只要啟用了安裝演示數(shù)據(jù)洲敢,下次更新時(shí),這些內(nèi)容就會(huì)被導(dǎo)入茄蚯。
??數(shù)據(jù)文件會(huì)在模塊升級(jí)時(shí)重新導(dǎo)入压彭,但演示文件則并非如此,它們僅在安裝時(shí)導(dǎo)入渗常。
當(dāng)然 XML 文件也可用于加載或初始化數(shù)據(jù)哮塞,還可使用普通 CSV 文件所不具備的功能。
使用 XML 數(shù)據(jù)文件
CSV 文件是一種展示數(shù)據(jù)方便簡(jiǎn)潔的格式凳谦,但 XML 文件更為強(qiáng)大忆畅,可在加載過程中提供更多的控制。比如尸执,其文件名無需與所導(dǎo)入到的模型名稱一致家凯。因?yàn)閄ML格式通過文件內(nèi)的XML元素可以提供更豐富的信息、更多的內(nèi)容如失。
在前面的文章中我們已經(jīng)使用過XML數(shù)據(jù)文件绊诲。視圖和菜單項(xiàng)這類用戶界面組件實(shí)際上都是存儲(chǔ)在系統(tǒng)模型中的記錄。模塊中的XML文件是將這些記錄加載到實(shí)例數(shù)據(jù)庫(kù)的方式褪贵。我們將在library_app模塊中添加一個(gè)數(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 文件脆丁,該文件也會(huì)將數(shù)據(jù)加載到圖書模型中世舰。
XML文件包含一個(gè)外層<odoo>元素,內(nèi)部可包含多個(gè)<record>元素與對(duì)應(yīng) CSV 數(shù)據(jù)行槽卫。
??數(shù)據(jù)文件中的外層<odoo>元素在9.0中才引入用于替換此前的<openerp>標(biāo)簽「梗現(xiàn)在仍支持外層元素內(nèi)的<data>標(biāo)簽,為可選項(xiàng)歼培。事實(shí)上現(xiàn)在<odoo>和<data>是等價(jià)的震蒋,我們可以在數(shù)據(jù)文件中使用任意一個(gè)作為外層元素茸塞。
<record>元素有兩個(gè)強(qiáng)制屬性: model 和作為記錄外部標(biāo)識(shí)符的 id,每個(gè)字段使用一個(gè)<field>標(biāo)簽來進(jìn)行寫入查剖。注意此處字段名內(nèi)不可使用斜杠標(biāo)記钾虐,如不可使用<field name="publisher_id/id">。應(yīng)使用 ref 屬性來引用外部標(biāo)識(shí)符笋庄,一會(huì)兒就會(huì)討論到關(guān)聯(lián) to-many 字段效扫。
你可能注意到在外層元素中使用了noupdate="1"屬性。這防止了在模塊升級(jí)時(shí)數(shù)據(jù)記錄的載入无切,不至于在后續(xù)編輯中丟失數(shù)據(jù)荡短。
noupdate 數(shù)據(jù)屬性
升級(jí)模塊時(shí),會(huì)重新加載數(shù)據(jù)并重寫模塊記錄哆键。要謹(jǐn)記這可能意味著在升級(jí)模塊時(shí)會(huì)重寫任何對(duì)模塊數(shù)據(jù)的手動(dòng)更改掘托。
小貼士:值得注意的是,手動(dòng)對(duì)視圖所做的自定義修改會(huì)在下一次模塊升級(jí)時(shí)丟失籍嘹。避免這一問題正確的方法是創(chuàng)建繼承視圖來引入要做的修改闪盔。
這種重寫行為是默認(rèn)的,但可以修改有些數(shù)據(jù)僅在安裝時(shí)導(dǎo)入辱士,后續(xù)模塊更新時(shí)則予以忽略泪掀,這正是通過<odoo>或<data>元素中的noupdate="1"來實(shí)現(xiàn)的。
這對(duì)于需初始化配置且預(yù)期需自定義的數(shù)據(jù)來說非常有用颂碘,因?yàn)檫@些手動(dòng)修改在模塊更新時(shí)是安全的异赫。例如在記錄訪問規(guī)則中經(jīng)常使用,可以適應(yīng)具體的實(shí)施需求头岔。
在同一 XML 文件中可以有多個(gè)<data>版塊塔拳。可通過這個(gè)來分隔僅需導(dǎo)入一次的數(shù)據(jù)(noupdate="1")和需在每次更新時(shí)重新導(dǎo)入的數(shù)據(jù)(noupdate="0")峡竣。noupdate="0"是默認(rèn)值靠抑,所以可以省略不寫。注意還必須要有一個(gè)外層 XML 元素适掰,就這個(gè)例子而言颂碧,使用兩個(gè)<data>標(biāo)簽,并在外層包裹一個(gè)<odoo>或<data>元素类浪。
小貼士:noupdate屬性在開發(fā)模塊時(shí)可能會(huì)引起不適载城,因?yàn)闀?huì)忽略后續(xù)修改。一個(gè)解決方案是戚宦,使用-i 參數(shù)重新安裝模塊而不是使用-u 參數(shù)進(jìn)行更新个曙。命令行中使用-i 參數(shù)重新安裝會(huì)忽略數(shù)據(jù)記錄中的noupdate標(biāo)記。
noupdate標(biāo)記存儲(chǔ)在每條記錄的外部標(biāo)識(shí)符信息中受楼】寻幔可通過 Technical 菜單中的External Identifiers表單手動(dòng)編輯,勾選Non Updatable 復(fù)選框即可艳汽。
??Odoo 12中的修改
點(diǎn)擊開發(fā)者菜單中的View Metadata時(shí)猴贰,現(xiàn)在在彈出的對(duì)話框中 XML ID 下面還會(huì)顯示No Update的值。并且在該處可通過點(diǎn)擊來修改該標(biāo)記的值河狐。
在 XML 中定義記錄
在 XML 文件中米绕,每個(gè)<record>元素有兩個(gè)基本屬性:id 和 model,并包含為對(duì)應(yīng)列設(shè)置的值馋艺。 id 屬性對(duì)應(yīng)記錄外部標(biāo)識(shí)符栅干,model 對(duì)應(yīng)目標(biāo)模型。<field>元素有幾種分配值的方法捐祠,下面一起來看看碱鳞。
直接為字段設(shè)置值
<field>元素的 name 屬性標(biāo)識(shí)要寫入的字段。寫入的值是元素內(nèi)容:字段開踱蛀、閉標(biāo)簽之間的文本窿给。對(duì)于 date 和datetime,帶有返回 date 或 datetime 對(duì)象表達(dá)式的 eval 屬性可進(jìn)行設(shè)置率拒。返回的"YYYY-mm-dd"和"YYYY-mm-dd HH:MM:SS"字符串會(huì)進(jìn)行轉(zhuǎn)化崩泡。對(duì)于布爾字段,"0" and "False"都會(huì)轉(zhuǎn)換成 False猬膨,而任意非空值都會(huì)轉(zhuǎn)換成 True角撞。
小貼士:Odoo 10中的修改
Odoo 10中改進(jìn)了從數(shù)據(jù)文件中讀取布爾值 False的方式。在老版本中勃痴,包含"0" and "False"在內(nèi)的非空值都會(huì)轉(zhuǎn)換成 True谒所,直至 Odoo 9,布爾值仍需使用 eval 屬性進(jìn)行設(shè)置召耘,如 eval="False"百炬。
通過表達(dá)式設(shè)置值
設(shè)置字段值更復(fù)雜的方式是通過 eval 屬性,它會(huì)運(yùn)行 Python 表達(dá)式并將結(jié)果分配給字段污它。表達(dá)式通過 Python 內(nèi)置的以及一些其它可創(chuàng)建表達(dá)式標(biāo)識(shí)符的上下文求值剖踊。
可使用如下 Python 模塊來處理日期:time, datetime, timedelta和relativedelta。通過它們可以計(jì)算日期值衫贬,在演示和測(cè)試數(shù)據(jù)經(jīng)常會(huì)用到德澈,以讓日期和模塊安裝日期較近。關(guān)于 Python 模塊更多這類知識(shí)固惯,請(qǐng)參考官方文檔梆造。
比如,把值設(shè)為前一天,可使用如下代碼:
<field name="date_published"
eval="(datetime.now() + timedelta(-1))" />
求值上下文還可使用ref()函數(shù)镇辉,用于將外部標(biāo)識(shí)符轉(zhuǎn)換為對(duì)應(yīng)的數(shù)據(jù)庫(kù) 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è)置值
對(duì)于many-to-one關(guān)聯(lián)字段村砂,要寫入的是關(guān)聯(lián)記錄的數(shù)據(jù)庫(kù) ID。在 XML 文件中屹逛,我們一般會(huì)知道記錄的XML ID础废,然后就需要把它轉(zhuǎn)換成實(shí)際的數(shù)據(jù)庫(kù) ID。
一種方式是像前文那樣使用帶有 ref()函數(shù)的 eval 屬性罕模。更簡(jiǎn)單的替代方式是使用在元素中可用的ref 屬性评腺,使用它設(shè)置publisher_id many-to-one字段的值,我們可以這么寫:
<field name="publisher_id" ref="res_partner_packt" />
在 to-many 關(guān)聯(lián)字段上設(shè)置值
對(duì)于one-to-many和many-to-many字段淑掌,設(shè)置的不是單個(gè) ID蒿讥,而是一組關(guān)聯(lián) ID。并且還進(jìn)行幾種操作-我們可能需要將當(dāng)前的關(guān)聯(lián)記錄列表替換成另外一個(gè)锋拖,或?yàn)槠涮砑訋状斡涗浾┖罚踔潦莿h除其中的一些記錄。
要讓to-many字段支持寫操作兽埃,我們要在 eval 屬性中使用一種特殊的語(yǔ)法侥钳。我們使用一個(gè)元組組成的列表來寫入to-many字段。每個(gè)元組有三個(gè)元素柄错,構(gòu)成一個(gè)寫入命令舷夺,根據(jù)第一個(gè)元素中的代碼進(jìn)行對(duì)應(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'))]"
/>
上述的例子非常常見。這里僅使用了一個(gè)命令颂跨,但在外層列中可以串聯(lián)多條命令敢伸。添加(4)和 替換(6)是最常用的命令。在進(jìn)行添加(4)時(shí)恒削,不需要使用最后一個(gè)元素池颈,因此在以上代碼中省略了。
完整的可用命令如下:
- (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)
常用模型的簡(jiǎn)寫
如果回到第三章 Odoo 12 開發(fā)之創(chuàng)建第一個(gè) Odoo 應(yīng)用,我們?cè)?XML 中還發(fā)現(xiàn)<record>之外的元素李茫,如<act_window>和<menuitem>揭保。這些是常用模型的簡(jiǎn)寫方式,是比常用的<record>更為簡(jiǎn)練的符號(hào)涌矢。它們用于向 base 模型加載數(shù)據(jù)掖举、組成用戶界面快骗,在第十章 Odoo 12開發(fā)之后臺(tái)視圖 - 設(shè)計(jì)用戶界面會(huì)作更詳細(xì)的探討娜庇。
為便于查看,以下是可用的簡(jiǎn)寫元素以及加載數(shù)據(jù)的對(duì)應(yīng)模型:
- <act_window>是窗口操作模型ir.actions.act_window
- <menuitem>是菜單項(xiàng)模型ir.ui.menu
- <report>是報(bào)表操作模型ir.actions.report.xml
- <template>是存儲(chǔ)在ir.ui.view模型中的 QWeb 模板
??Odoo 11中的修改
<url>標(biāo)簽已被淘汰并刪除方篮。此前的版本中它用作為 URL 操作模型ir.actions.act_url加載記錄名秀。
應(yīng)當(dāng)注意在用于修改已有記錄時(shí),簡(jiǎn)寫元素會(huì)覆蓋所有字段藕溅。這與僅寫入所提供字段的<record>基礎(chǔ)元素不同匕得。因此在需修改用戶界面元素指定字段時(shí),應(yīng)使用<record>元素巾表。
XML 文件中的其它操作
截至目前我們了解了如何使用 XML 文件添加和更新數(shù)據(jù)汁掠。但也可以通過 XML 文件刪除數(shù)據(jù)以及執(zhí)行指定模型方法。對(duì)更復(fù)雜的數(shù)據(jù)場(chǎng)景會(huì)非常有用集币。
刪除記錄
我們可以使用<delete>元素刪除數(shù)據(jù)記錄考阱,使用 ID 或搜索域來定位要?jiǎng)h除的記錄。例如鞠苟,使用搜索域查找記錄并刪除:
<delete
model="res.partner"
search="[('id','=',ref('library_app.res_partner_daniel'))]"
/>
如果知道要?jiǎng)h除記錄的具體 ID乞榨,可使用 id 屬性。上例還可以寫成這樣:
<delete model="res.partner" id="library_app.res_partner_daniel" />
調(diào)用模型方法
XML 文件還可以通過<function>元素在加載過程中執(zhí)行任意方法当娱,可用于設(shè)定演示和測(cè)試數(shù)據(jù)吃既。比如 Odoo 捆綁的 Notes 應(yīng)用,使用它來設(shè)定演示數(shù)據(jù):
<data noupdate="1">
<function
model="res.users"
name="_init_data_user_note_stages"
eval="[]" />
</data>
這會(huì)調(diào)用res.users模型中的_init_data_user_note_stages方法跨细,不傳任何參數(shù)鹦倚。由參數(shù)列表eval傳遞,此處為空列表冀惭。
總結(jié)
本文中我們學(xué)習(xí)了如何在文件文中展示數(shù)據(jù)震叙。可用作手動(dòng)向 Odoo 導(dǎo)入數(shù)據(jù)云头,或放在插件模塊中作為默認(rèn)或演示數(shù)據(jù)捐友。通過學(xué)習(xí)我們可以通過網(wǎng)頁(yè)界面導(dǎo)出并導(dǎo)入 CSV 數(shù)據(jù)文件了,以及通過外部 ID 來檢測(cè)并更新數(shù)據(jù)庫(kù)中已有的記錄溃槐。也可用作批量編輯數(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é)作拂共。這些工具可供我們實(shí)現(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>
- 一個(gè)插件模塊中的數(shù)據(jù)文件是否可以覆蓋另一個(gè)模塊中創(chuàng)建的記錄?
- 插件模塊升級(jí)時(shí)抚恒,是否所有數(shù)據(jù)記錄都會(huì)被重寫為模塊默認(rèn)值咱台?
擴(kuò)展閱讀
Odoo 官方文檔中提供了有關(guān)數(shù)據(jù)文件的更多資料。
本文首發(fā)地址:Alan Hou的個(gè)人博客