今天要跟大家分享的是Odoo中的继承,继承功能体现在几个方面,有后台数据模型的继承(含模型方法的继承、模型字段的继承)、前端各种view的继承、JS方法的继承等。
模型继承
Odoo提供了两种继承机制,以模块化方式扩展现有模型。
第一类继承机制允许模块修改另一个模块中定义的模型的如下行为:
将字段添加到模型中,
覆盖模型上字段的定义,
为模型添加约束,
向模型添加方法,
覆盖模型上的现有方法。
第二类继承机制(委托)允许将当前模型的每个记录无缝链接到父模型中的记录,并提供对父记录字段的透明访问。
官方对于模型继承的机制有一个图示说明:

第一类继承有两种写法,主要是看_name与_inherit是否相同的判断,如果两者相同,或者新定义的模型没有_name变量,则表示新模型是在原有的模型基础上进行功能扩展。可以增加新的字段、方法,或者重写原有的方法,在数据库层面,这两个模型对应的是同一个数据表;如果_name与_inherit变量不相同,则新模型是通过复制原模型的方式,生成一个包含原模型字段和方法的新数据模型,新模型还可以扩充自己的字段和方法,在数据库层面,新模型是单独的数据表,新旧模型的数据没关联,这种情况下还允许进行多重继承。
第二类继承通过_inherits定义,不可以省略_name变量,这类定义在ORM层会包含原模型的所有字段和方法,通过新模型的API也可以处理原模型的数据,在数据库层面,新旧模型是两个不同的数据表,但在新表中会有一个字段与原模型进行关联。如产品模块中的product.product就是通过这种方法来继承product.template,根据产品模板来生成不同规格型号的产品明细。
视图继承
在Odoo中要更改现有视图的展示,也可以通过视图继承添加或删除其父视图中的内容。
扩展视图使用inherit_id字段引用其父级视图ID,其arch字段由任意数量的xpath元素组成,用于选择和更改其父视图的内容:
<record id="idea_category_list2" model="ir.ui.view"><field name="name">id.category.list2</field><field name="model">idea.category</field><field name="inherit_id" ref="id_category_list"/><field name="groups_id" eval="[(4, ref('group_pos_user'))]"/><field name="arch" type="xml"><xpath expr="//field[@name='description']" position="after"><field name="idea_ids" string="Number of ideas"/></xpath></field></record>
其中inherit_id节点指定父级视图的ID,如果是不同模块的视图,这里还要加上模块名称前缀;groups_id节点是可选项,如果不指定,则该继承是全局有效,如果有指定,则只有当前用户归属于指定群组时才有效,这个选项可以根据群组不同来实现不同的显示界面。比如有些业务需求中,普通用户对于某些字段是只读或隐藏,管理用户才可以修改或查看,那我们可以先建立一个针对普通用的View,然后再继承增加一个针对管理用户的View来进行修改扩充。
上面定义中arch节点中可以包括多个XPATH表达式来定位需要修改的元素,关于xpath的表达式内容可以自己去某度搜索。这里主要再说说position的类型,可选值有'inside','before','after','replace','attributes'。这里表示通过xpath表达式找到原有的元素以后,怎么来处理新元素的方法,inside表示在原元素内部追加新元素内容,before表示在原元素前面插入新元素内容,after表示在原元素后面插入新元素内容,replace表示用新元素替换原元素内容,attributes表示修改原元素的属性值。
JS继承
在Odoo中,除了后端的模型业务进行继承以外,也可能会需要对前端的JS进行继承修改,与模型继承类似,JS的继承也会两种情况,一种是在原业务对象上扩展新的功能,另一种是根据原业务对象生成一个新的业务对象。
第一种继承主要通过include方法实现,如:
var KanbanRecord = require('web.KanbanRecord');KanbanRecord.include({_openRecord: function () {if (this.modelName === 'project.project' && this.$(".o_project_kanban_boxes a").length) {this.$('.o_project_kanban_boxes a').first().click();} else {this._super.apply(this, arguments);}},})
在include的参数对象中,可以对原业务对象进行方法重写,一般重写都不会改变原有的业务逻辑,所以在重写的方法中都会有this._super.apply来保留原有的业务逻辑。
第二种继承通过extend来实现,如:
var FormRenderer = require('web.FormRenderer');var QuickCreateFormRenderer = FormRenderer.extend({start: function () {this.$el.addClass('o_xxs_form_view');return this._super.apply(this, arguments);},})
因为第二种方法是通过继承来生成一个新的业务对象,所以extend的返回值都会赋予一个新的变量,extend的参数对象与include一致,只是在使用的时候,如果调用原业务对象的方法,不会有extend扩充的业务逻辑。
以上是有关Odoo中的继承相关的分享,如果你喜欢我们的内容,请记得分享转发,下期精彩敬请期待。。。




