Odoo 18 中的继承类型详解
在 Odoo 中,继承机制允许开发者无需修改核心系统即可扩展、修改或定制现有模型、视图和功能。这种模块化设计确保自定义内容在系统升级后仍可维护。Odoo 18 主要提供三种继承类型:Python 继承、模型继承和视图继承,每种继承类型服务于特定场景,使 Odoo 能够灵活适配各类业务需求。
一、Python 继承(逻辑层继承)
Python 继承用于扩展或重写现有模型的方法和业务逻辑。所有模型默认继承自 Odoo 的基类 models.Model,从而获得基础的 CRUD(创建、读取、更新、删除)功能。
核心特点
- 方法重写:通过 super() 调用父类方法,在不破坏原有逻辑的前提下添加自定义功能。
- 应用场景:修改模型的创建、更新逻辑,或添加业务校验规则。
示例:扩展创建方法
新建一个 test.model 模型,名称介绍为测试模型:
from odoo import models, api class TestModel(models.Model): _name = "test.model" _description = "测试模型" @api.model def create(self, vals): # 创建记录前添加自定义逻辑(如日志记录、字段预处理) vals['custom_field'] = '默认值' # 动态设置字段值 return super(TestModel, self).create(vals) # 调用父类创建方法
上述代码中,create 方法被重写,在创建记录前为 custom_field 设置默认值,同时保留原有创建逻辑。
二、模型继承(数据模型继承)
模型继承用于扩展现有模型的字段或功能,分为三种类型:经典继承、扩展继承和委托继承。
1. 经典继承(Classical Inheritance)
- 特点:创建新模型,继承父模型的所有字段、方法和元数据,并可新增或重写内容。
- 使用 _inherit 指定父模型,同时通过 _name 定义新模型名称。
- 子类完全继承父类行为,可重写方法或添加新字段。
- 示例:动物与狗的继承关系
# 父模型:动物 class ZooAnimal(models.Model): _name = 'zoo.animal' _description = '动物' name = fields.Char('动物名称') def make_sound(self): return "发出声音" # 子类:狗(经典继承) class ZooDog(models.Model): _name = 'zoo.dog' _inherit = 'zoo.animal' # 经典继承,继承父模型 _description = '狗' def make_sound(self): return f"{self.name} 汪汪叫!" # 重写父类方法
ZooDog 模型继承自 ZooAnimal,并重写了 make_sound 方法,实现特定行为。
2. 扩展继承(Extension Inheritance)
- 特点:直接扩展现有模型,无需创建新模型。通过 _inherit 引用目标模型,直接添加字段或修改方法。
- 不定义 _name,直接作用于原模型,相当于 “Mixin” 机制。
- 示例:为图书模型添加作者字段
# 扩展 library.book 模型(原模型由其他模块提供) class ExtendedBook(models.Model): _inherit = 'library.book' # 扩展原有模型 author = fields.Char('作者', default="佚名") # 新增字段
上述代码为 library.book 模型动态添加 author 字段,原模型的所有实例将自动包含该字段。
3. 委托继承(Delegation Inheritance)
- 特点:通过关联字段(如 Many2one)实现字段 “继承”,子类可访问父类字段,但不继承方法。
- 使用 _inherits 参数建立关联,语法为 {'父模型': '关联字段名'}。
- 子类与父类是独立模型,但子类可通过关联字段透明访问父类字段。
- 示例:产品变体继承模板字段
from odoo import fields, models # 产品模板(父模型) class ProductTemplate(models.Model): _name = "product.template" _description = "产品模板" name = fields.Char(string='产品名称', required=True) list_price = fields.Float(string='销售价格') # 产品变体(委托继承) class ProductProduct(models.Model): _name = "product.product" _inherits = {'product.template': 'product_tmpl_id'} # 关联字段为 product_tmpl_id product_tmpl_id = fields.Many2one( 'product.template', required=True, ondelete="cascade" # 级联删除 ) sku = fields.Char(string='SKU') # 子类特有字段
ProductProduct 通过 product_tmpl_id 关联 ProductTemplate,可直接使用 name 和 list_price 字段,但不会继承 ProductTemplate 的方法。
三、视图继承(界面层继承)
视图继承通过 XPath 表达式修改现有视图,无需直接编辑原始 XML 文件,确保系统升级时自定义内容可保留。
核心机制
- 使用 inherit_id 指定父视图,通过 xpath 标签定位目标元素。
- 定位方式:
- expr:XPath 表达式,用于匹配视图中的元素(如字段、按钮、容器)。
- position:操作方式,包括 after(在目标元素后插入)、before(在目标元素前插入)、replace(替换目标元素)、inside(在目标元素内部插入)。
示例:在销售订单表单添加自定义字段
<record id="sale_order_form_inherit" model="ir.ui.view"> <field name="name">sale.order.form.custom</field> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_order_form"/> <!-- 继承原表单视图 --> <field name="arch" type="xml"> <!-- 在客户参考号字段后添加内部编号字段 --> <xpath expr="//field[@name='client_order_ref']" position="after"> <field name="custom_internal_ref" string="内部编号"/> </xpath> </field> </record>
四、核心对比表
继承类型 | 应用场景 | 关键标识 | 特点 |
---|---|---|---|
Python 继承 | 扩展/重写模型方法 | _inherit | 使用 super() 保留原有逻辑,专注于业务逻辑层的定制。 |
经典继承 | 创建新模型并继承功能 | _name + _inherit | 生成独立子类,支持方法重写和字段扩展,完全继承父模型行为。 |
扩展继承 | 直接扩展现有模型 | _inherit | 无独立模型,直接修改原模型,适用于添加新字段或修改字段属性(Mixin 机制)。 |
委托继承 | 通过关联字段复用父模型字段 | _inherits | 子类与父类独立,通过 Many2one 关联,字段透明访问但不继承方法。 |
视图继承 | 定制界面布局 | XML + XPath | 非破坏性修改,通过 XPath 精准定位元素,支持版本升级兼容。 |
五、总结
Odoo 的继承机制通过 Python 继承(逻辑层)、模型继承(数据层,含经典/扩展/委托三种模式)和 视图继承(界面层),为开发者提供了从功能逻辑到用户界面的全方位扩展能力。合理使用这些继承类型可确保自定义代码的模块化和可维护性,同时兼容 Odoo 的版本升级。开发者需根据具体场景选择合适的继承方式,避免过度修改核心代码,保持系统的可扩展性和稳定性。