Inheritance and extension
Odoo 提供了三種不同機制用來擴展models in a modular way:
- 繼承一個已經存在的model,添加一些新的屬性或者方法,但是,源model不會增加屬性或方法,只是自己改變
- 在另外一個 Odoo module 中,直接擴展源model,給他添加新的屬性或方法,而不用去修改源碼
- delegating some of the model’s fields to records it contains
Classical inheritance
當同時使用_inhert
和 _name
屬性時,Odoo 將根據 _inherit
創建一個名爲 _name
的新的model,這個新的 model 將從_inherit
的 model 中獲取所有的 fields,methods,meta-information。
class Inheritance0(models.Model):
_name = 'inheritance.0'
name = fields.Char()
def call(self):
return self.check("model 0")
def check(self, s):
return "This is {} record {}".format(s, self.name)
class Inheritance1(models.Model):
_name = 'inheritance.1'
_inherit = 'inheritance.0'
def call(self):
return self.check("model 1")
你這樣調用
a = env['inheritance.0'].create({'name': 'A'})
a.call()
b = env['inheritance.1'].create({'name': 'B'})
b.call()
產生下述結果
This is model 0 record A
This is model 1 record B
第二個 model 繼承了第一個 model 的 name field 和 check method,但是覆蓋了它的 call method,這種繼承方式和普通的 Python 繼承一樣。
Extension
當只設置了_inherit
,沒有設置_name
屬性時,這個新的 model 就是直接對源 model 進行了擴展。這種機制通常是在其他 module 中對已有 module 中的model進行添加字段或方法,或者重新定製化他們(如:改變他們的默認 search order)
class Extension0(models.Model):
_name = 'extension.0'
name = fields.Char(default="A")
class Extension1(models.Model):
_inherit = 'extension.0'
description = fields.Char(default="Extended")
record = env['extension.0'].create({})
record.read()[0]
將產生
{'name': "A", 'description': "Extended"}
當然,也會返回一些 自動建立的字段值,’create_uid’ 之類的
Delegation
第三種機制就更加的靈活了,使用_inherits
屬性,using the _inherits a model delegates the lookup of any field not found on the current model to “children” models. The delegation is performed via Reference fields automatically set up on the parent model:
class Child0(models.Model):
_name = 'delegation.child0'
field_0 = fields.Integer()
class Child1(models.Model):
_name = 'delegation.child1'
field_1 = fields.Integer()
class Delegating(models.Model):
_name = 'delegation.parent'
_inherits = {
'delegation.child0': 'child0_id',
'delegation.child1': 'child1_id',
}
child0_id = fields.Many2one('delegation.child0', required=True, ondelete='cascade')
child1_id = fields.Many2one('delegation.child1', required=True, ondelete='cascade')
record = env['delegation.parent'].create({
'child0_id': env['delegation.child0'].create({'field_0': 0}).id,
'child1_id': env['delegation.child1'].create({'field_1': 1}).id,
})
record.field_0
record.field_1
f返回
0
1
可以直接對託管的字段進行修改:
record.write({'field_1': 4})
使用這種機制,只有 field 會被繼承,method 不會。
Domains
一個 domain 就是一些條件組成的 list,每一個條件都是由3個元素組成,(field_name
, operator
, value
)
field_name (str)
當前model 的一個 field name,或者是 Many2one field 組成 dot 鏈。如:'street'
,'partner_id.country'
operator(str)
用來比較field_name
和value
,有:
=
!=
>
>=
<
<=
=?
這個字段如果有值,就用=
比較;如果這個字段值爲 False 或者 None,返回 True=like
這個字段是否滿足value
pattern,在 pattern 中_
代表 一個任意字符,%
代表0或多個任意字符。like
pattern 直接就是%value%
not like
ilike
不區分大小寫的like
not ilike
=ilike
不區分大小寫的=like
in
value
should be a list of itemsnot in
child_of
value
variable type, must be comparable (through operator) to the named field
Domain 中的條件可以通過下面的邏輯運算符鏈接起來:
&
邏輯 AND, 兩個參數,將會默認的鏈接相鄰的兩個條件|
邏輯 OR, 兩個參數!
邏輯 NOT,一個參數
注意:表示否定的時候,儘量在條件中的 operator 表示,這樣比在外面表示更加的清晰明瞭。
[('name','=','ABC'),
('language.code','!=','en_US'),
'|',('country_id.code','=','be'),
('country_id.code','=','de')]
這個翻譯過來就是
(name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)