轉載請注明原文地址:https://www.cnblogs.com/ygj0930/p/10826114.html
在實際開發過程中,經常會遇到需要修改Odoo原生邏輯的情況。然而,直接修改Odoo底層代碼,不利於后面odoo版本迭代時替換。因此,在不改變底層對象的時候添加新的功能,就顯得十分重要。
Odoo提供繼承機制來實現這個目的,繼承修改可以發生:Python代碼和XML視圖、Qweb模版上。
一:模型繼承
1:模型修改
# -*- coding: utf-8 -*- from odoo import models, fields, api class Sub(models.Model): _inherit = 'Root' //通過_inherit屬性來繼承父模型 newCol=fields.XX.... //在下面添加新字段即可。
1)添加字段
如上,直接定義新字段即可。
2)修改現有字段
為了改變現有字段的屬性,只需再次定義該同名字段,需要修改的屬性顯式重寫即可,會保留未修改的所有其他未在此處明確使用的字段的屬性。
3)添加方法
添加新方法很簡單:只需在繼承類中聲明新的函數。
4)修改方法
擴展或更改現有邏輯,可以通過聲明具有完全相同名稱的方法來覆蓋相應的方法。
新方法將替換前一個方法,它可以只是擴展繼承類的代碼,使用Python的super()方法來調用父方法。然后,可以在調用super()方法之前和之后,在原有邏輯周圍添加新邏輯。
2:模型繼承的方式
1)類繼承
擴展類中沒有_name屬性,因為它繼承了父類的_name。對現有模型的擴展, 添加新功能,都將添加到現有模型中,不會創建新模型。 因此,在odoo中,根據_name唯一確定這個模型時找到的就是擴展后的類。(如上面添加字段是類繼承)
2)原型繼承(帶name繼承,創建新的表)
我們想使用具有不同於父模型的值的_name屬性,我們將獲得一個新模型重用來自繼承的特性,但是具有自己的數據庫表和數據。其實就是把繼承的類的功能特性拷貝給新的模型使用,並不改變被繼承模型。
復制意味着被繼承的方法和字段也將在繼承模型中可用。 對於字段,這意味着它們也將被創建並存儲在目標模型的數據庫表中。 原始(繼承)和新(繼承)模型的數據記錄保持不相關,只有定義是共享的。
3)代理繼承(委托繼承)【以成員變量的形式把父類對象包含進來】
使用_inherits屬性,它允許一個模型以透明的方式包含其他模型。通過字典映射繼承模型與字段的關系,並關聯它們。
通俗解釋:(相當於成員變量:引用一個外部的類對象賦值給這個模型的一個成員,但是對象的值是保存在被引用的類的數據庫表中的。但是在當前類通過成員修改了變量值,則會同步到被引用的類的數據庫表中)
優點是不需要在幾個表之間重復數據結構,例如地址。 任何需要包含地址的新模型都可以將其委派給嵌入式合作伙伴模型。 如果在合作伙伴地址字段中引入了修改,則這些修改會立即提供給嵌入它的所有模型!
二:視圖繼承
表單,列表和搜索視圖是使用arch XML結構定義的,要擴展視圖,我們需要一種方法來修改這個XML。 這意味着需要定位XML中的元素位置,然后在這些位置引入修改。
對於XML,在其中定位元素的最好方法是使用XPath表達式,如果XPath表達式匹配到多個元素,只有第一個元素會被修改。
因此,表達式應該使用獨特的屬性以使其指定盡可能具體,使用name屬性是確保我們找到擴展點的確切xml元素的最簡單方法。 因此,在我們的視圖XML元素上定義name屬性是很重要的。
Xpath表達式的格式:expr="//標簽名[@屬性]='屬性值'" 意思是:找到 屬性=屬性值 的標簽的位置。
下面是一個寫在arch中的實現在is_done字段之前添加date_deadline字段的具體例子:
<xpath expr="//field[@name]='is_done'" position="before"> //expr屬性值的意思是:找到<filed name="is_done"/>的標簽 <field name="date_deadline" /> </xpath>
Odoo為此提供了快捷符號,因此大多數時候我們可以完全避免XPath語法。 我們僅使用要定位的元素的特定屬性及定位類型相關信息就可以了。
<field name="is_done" position="before"> <field name="date_deadline" /> </field>
【如果字段在同一視圖中多次出現,則應始終使用XPath語法。】
position屬性是可選的:
after:將內容添加到父元素之中,匹配的節點之后。 before:添加內容在匹配節點之前。 inside(默認值):匹配節點內的追加內容。 replace:替換匹配的節點。如果使用空內容,它將刪除該匹配的元素。 attributes:修改匹配元素的XML屬性。在元素內容使用<attribute name =“attr-name”>實現給標簽設置新屬性值attr-name。
1.如果<attribute></attribute>之間有值,就在匹配的節點上添加以name命名的、以內容主體為值的屬性或是修改原同名屬性值。
2.如果<attribute></attribute>沒有值,就將匹配節點上名字為name的屬性刪除,如果原節點上沒有對應的屬性,拋出一個錯誤。
下面是視圖繼承的模版寫法:
1)擴展表單視圖
<record id="view_form_模塊名_inherited" model="ir.ui.view"> <field name="name">模塊名_extension</field> <field name="model">模型名</field> <field name="inherit_id" ref="模塊_模型.被繼承的form表單id"/> <field name="arch" type="xml"> //在arch中進行擴展操作:定位—>插入/修改 <field name="定位標簽name" position="在標簽的哪里進行擴展"> <field ......> //擴展內容 </field> </field> </record>
2)擴展列表視圖
<record id="view_tree_模型名_inherited" model="ir.ui.view"> <field name="name">模型名 extension</field> <field name="model">模型</field> <field name="inherit_id" ref="被繼承的tree視圖id"/> <field name="arch" type="xml">//在arch中進行擴展 <field name="定位標簽name" position="擴展位置"> <field ....進行擴展 /> </field> </field> </record>
3)擴展搜索視圖
<record id="view_filter_模型名_inherited" model="ir.ui.view"> <field name="name">xxxextension</field> <field name="model">模型名</field> <field name="inherit_id" ref="被繼承的搜索視圖id"/> <field name="arch" type="xml"> //下面進行定位、擴展舉例 <field name="定位的標簽name" position="after"> //引入的修改,可以是增加過濾field,也可以定義 filter </field> </field> </record>
三:Qweb繼承
Qweb繼承是通過qweb語法來書寫的。但是思路一致:定位——>引入擴展
Qweb文件繼承分兩種:Qweb視圖類型的文件和data類型的文件,二者繼承修改的方式不同。
1:視圖類型的qweb文件繼承
視圖類型的qweb文件,一般定義的都是一些視圖模板,template中的內容大多用html+qweb語句編寫,如widget的視圖定義、odoo中各個界面的定義。
1)在statc/xml目錄下新建一個xml文件
2)編寫以下內容
<?xml version="1.0" encoding="UTF-8"?>
<template id="唯一的id" xml:space="preserve">
<t t-extend="要繼承擴展的template的name屬性值">
<t t-jquery="使用選擇器來定位" t-operation="相當於position">
//擴展的內容,一般用html語法+qweb語句編寫
</t>
</t>
</template>
3)在manifest文件中,配置到qweb配置項:
"qweb": [
"static/src/xml/qweb_file.xml",
],
2:data類型的qweb文件繼承
data類型的qweb文件,一般是一些輔助界面qweb的文件,大多用於定義、引入css文件等,多處於view目錄下。
1)在views目錄下新建一個xml文件
2)編寫以下內容
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="唯一id" inherit_id="模塊.繼承的templateid">
<xpath expr="xpath定位語句">
//引入的內容,一般是link標簽和script標簽,把static/src目錄下的css、js子目錄的文件引入
</xpath>
</template>
</odoo>
3)在manifest文件中配置data,把文件加載
"data": [
"views/XXX.xml",
],