如何在 Odoo 19 中使用模型属性
你是否曾思考过,是什么让 Odoo 模型具备如此出色的适应性和高效性?无论你已经在使用 Odoo 进行开发,还是刚刚开始探索,熟练掌握模型属性都将为你带来颠覆性的提升。在 Odoo 19 中,这些属性是业务逻辑的基石------它们控制着数据的存储方式、系统的响应逻辑,甚至记录在界面中的展示形式和行为。理解这些属性,你就能真正掌握定制化应用的核心能力。

你可以将模型属性理解为指导 Odoo 处理数据的指令集。它们定义了数据是存储到数据库、保留在内存中快速处理,还是作为其他模型继承的基础结构。这套灵活的系统,正是 Odoo 成为强大且可定制化业务应用开发平台的核心原因之一。
Odoo 模型的三大核心类型
在深入学习各类属性之前,我们先了解构成所有 Odoo 应用基础的三种核心模型类型:
1. 普通模型(Model)------ 应用的核心主力
持久化存储到数据库的普通模型,是 Odoo 应用的基础核心。这类模型代表你的核心业务实体,例如客户、产品、销售订单和发票。通过这些模型创建的每一条记录都会永久保存在数据库中,且跨会话持久生效。当你创建客户记录或生成发票时,就是在使用普通模型。
适用场景:客户档案、产品目录、销售订单、会计分录------所有需要永久存储和查询的数据。
python
# -*- coding: utf-8 -*-
class LibraryBook(models.Model):
_name = 'library.book' # 模型唯一技术名称
_description = '图书馆图书管理' # 可读的模型名称
_table = 'library_book' # 自定义数据库表名(可选)
_rec_name = 'name' # 用作记录展示名称的字段
_order = 'name asc' # 默认排序规则
_inherit = [] # 继承的现有模型(如需)
_inherits = {} # 委托继承(父模型: 关联ID字段)
_abstract = False # 抽象模型设为 True
_transient = False # 临时向导模型设为 True
_auto = True # 自动创建数据库表
_register = True # 在 ORM 中注册模型
_parent_name = 'parent_id' # 层级关系关联字段
_parent_store = False # 启用树形结构优化
_active_name = 'active' # 归档/取消归档使用的字段
_check_company_auto = True # 强制多公司数据一致性
_allow_sudo_commands = True # 允许对该模型执行 sudo 操作
_rec_names_search = ['name', 'isbn'] # 多对一字段搜索时使用的字段
# SQL 视图相关(仅当 _auto = False 时使用)
_table_query = None # 为基于视图的模型定义 SQL 查询
_depends = {} # SQL 视图模型的依赖关系
# 字段定义
name = fields.Char(string="图书名称", required=True)
isbn = fields.Char(string="ISBN编号")
author = fields.Char(string="作者")
active = fields.Boolean(string="启用", default=True)
parent_id = fields.Many2one(
'library.book',
string="父级图书",
ondelete='cascade'
)
2. 临时模型(TransientModel)------ 临时数据助手
临时模型专为临时数据设计,用于完成特定任务后自动清理。这类模型会将数据存储在数据库中,但自带自动销毁机制------系统会自动清理旧记录,避免数据库冗余。它们非常适合向导、临时计算和用户交互表单。
适用场景:向导表单、临时报表、数据导入/导出助手、无需永久存储的用户偏好弹窗。
python
# -*- coding: utf-8 -*-
class BookReportWizard(models.TransientModel):
_name = 'library.book.report.wizard' # 模型唯一名称
_description = '图书报表生成向导' # 展示名称
_table = 'library_book_report_wizard' # 自定义表名(可选)
_rec_name = 'name' # 界面中展示的字段
_order = 'id desc' # 默认排序
_inherit = [] # 经典继承(向导中极少使用)
_inherits = {} # 委托继承(不推荐在此使用)
_abstract = False # 非抽象模型
_transient = True # 标记为临时模型
_auto = True # 自动创建表
_register = True # 在 ORM 中注册
_transient_max_count = 1000 # 保留的最大记录数
_transient_max_hours = 1.0 # 自动删除超过 X 小时的记录
_parent_name = None # 向导中不使用
_parent_store = False # 无层级结构
_active_name = 'active' # 可选的归档支持
_check_company_auto = False # 通常无需配置
_allow_sudo_commands = True # 允许 sudo 操作
_rec_names_search = ['name'] # 搜索字段
# SQL 相关(临时模型不使用)
_table_query = None
_depends = {}
# 字段定义
name = fields.Char(string="向导名称")
date_from = fields.Date(string="开始日期")
date_to = fields.Date(string="结束日期")
active = fields.Boolean(string="启用", default=True)
3. 抽象模型(AbstractModel)------ 可复用的蓝图模板
抽象模型是实现代码高效复用的核心。它们不会创建独立的数据库表,而是作为其他模型继承的基础结构。你可以将其理解为可复用组件,提供共享的字段、方法和行为,让多个模型无需重复编写代码即可使用相同功能。
适用场景:邮件线程、网站发布功能等通用逻辑,或多个模型需要实现的共享行为。
python
# -*- coding: utf-8 -*-
class TimestampMixin(models.AbstractModel):
_name = 'timestamp.mixin' # 唯一技术名称
_description = '时间戳混合模型(通用日期字段)' # 展示名称
_table = None # 抽象模型不创建表
_rec_name = None # 抽象模型通常无需配置
_order = None # 无默认排序(不直接使用)
_inherit = [] # 可继承其他混合模型(如需)
_inherits = {} # 委托继承(抽象模型极少使用)
_abstract = True # 标记为抽象模型
_transient = False # 非临时模型
_auto = False # 不创建数据库表
_register = True # 注册模型以便被继承
_parent_name = None # 无层级关系
_parent_store = False # 无树形结构优化
_active_name = None # 无归档概念
_check_company_auto = False # 混合模型无需配置
_allow_sudo_commands = True # 默认允许 sudo 操作
_rec_names_search = [] # 不使用
# SQL 相关(不适用)
_table_query = None
_depends = {}
# 通用可复用字段
created_on = fields.Datetime(
string="创建时间",
default=fields.Datetime.now
)
updated_on = fields.Datetime(
string="最后更新时间"
)
模型属性完整详解
了解模型类型后,我们来学习全套模型属性,这些属性让你精准控制模型的行为:
核心标识属性
- _name (字符串) :模型的唯一标识符,采用点分隔格式。这是模型的唯一标识,在整个 Odoo 系统中必须唯一。示例:
'sale.order'、'res.partner'、'product.template'。 - _description (字符串 | None) :模型的可读名称,显示在用户界面、菜单和错误提示中。虽为可选配置,但对用户体验至关重要。示例:
'销售订单'、'客户'、'产品模板'。 - _module (字符串 | None):标识该模型所属的 Odoo 模块,用于管理模块依赖和结构。通常由框架自动设置。
- _custom (布尔值) :仅当模型通过 Odoo 工作室或自定义开发创建时,设为
True。用于区分 Odoo 核心模型和自定义扩展模型。
数据库与表管理
- _auto (布尔值) :控制 Odoo 是否自动为模型创建数据库表。如需手动创建表或使用数据库视图,设为
False。抽象模型默认值为True。 - _table (字符串):指定数据库中使用的精确 SQL 表名。未设置时,Odoo 会自动将模型名称中的点替换为下划线生成表名。
- _table_query (SQL 语句 | 字符串 | None):将模型内容定义为 SQL 表达式,本质是创建数据库视图而非普通表。非常适合复杂报表模型。
- _table_objects (字典):高级属性,用于定义与模型关联的 SQL/表对象,适用于复杂数据库操作和性能优化。
模型行为标记
- _register (布尔值) :控制模型是否注册到 Odoo 模型注册表并被框架识别。无需实例化的工具类可设为
False。 - _abstract (布尔值):标记模型为抽象模型。抽象模型不创建数据库表,仅用于被其他模型继承,实现功能共享。
- _transient (布尔值):标记模型为临时模型,其记录会在一段时间后被系统自动清理。适用于临时数据和向导。
继承与组合
- _inherit (字符串 | 字符串列表 | 元组) :定义 Python 风格的继承。设置了
_name时,代表继承的父模型;未设置_name时,直接扩展现有的模型,添加新字段和方法。 - _inherits (冻结字典):通过字典(父模型名称: 外键字段名)实现基于组合的继承。新模型可直接访问父模型的所有字段,但数据存储在关联的记录中。
- _inherit_children (有序集合):框架自动维护的子模型集合,记录继承自当前模型的所有子模型。用于框架内部的继承解析。
用户界面与展示
- _rec_name (字符串 | None) :在选择列表、多对一字段和面包屑导航中展示记录名称的字段。若存在
name字段,默认使用该字段;否则使用第一个字段。 - _rec_names_search (字符串列表 | None):用户在多对一字段或全局搜索中输入关键词时,用于检索的字段列表。支持多字段搜索,提升用户体验。
- _order (字符串) :未指定排序规则时,记录的默认排序方式。使用 SQL 的
ORDER BY语法。示例:'name asc'、'create_date desc, name'。 - _fold_name (字符串):用于判断看板视图分组是否折叠的字段名。通常是布尔字段,控制看板列的展开/折叠状态。
层级结构
- _parent_name (字符串):创建同模型记录父子关系的多对一字段。支持组织结构图、分类树等层级结构。
- _parent_store (布尔值) :通过计算
parent_path字段,启用层级数据的优化存储。大幅提升大型层级数据集的child_of和parent_of域操作性能。
记录归档管理
- _active_name (字符串 | None) :自动设置为
active或x_active,标识用于记录归档/取消归档的字段。启用的记录显示在普通视图中,归档记录隐藏但不会被删除。
本地化与翻译
- _translate (布尔值):控制模型字段是否包含在翻译导出文件中。该属性为遗留功能,未来版本可能会被废弃。
安全与权限控制
- _check_company_auto (布尔值) :自动对标记了
check_company=True的关联字段验证公司一致性。防止多公司环境下的数据泄露问题。 - _allow_sudo_commands (布尔值) :控制使用
sudo()或with_user()时,一对多、多对多操作是否可指向该模型。安全敏感模型应设为False,防止权限提升攻击。
高级性能优化
- _depends (冻结字典) :为 SQL 视图驱动的模型定义依赖关系,指定触发更新的模型字段。格式:
{模型名称: 字段名称列表}。用于缓存失效和数据库同步。
Odoo 19 中的扩展继承
python
class SaleOrder(models.Model):
"""
该类扩展现有的 `sale.order` 模型,添加自定义测试字段
技术说明:
- 使用经典继承(_inherit)
- 不创建新模型,仅扩展现有模型
"""
_inherit = 'sale.order' # 扩展现有的模型
test_field = fields.Char(
string="测试字段",
help="这是一个测试字段。",
)
Odoo 19 中的委托继承
python
class LibraryBook(models.Model):
"""
该模型演示通过 `_inherits` 实现与 `product.template` 的委托继承
核心概念:
- `_inherits` 通过多对一字段关联模型
- 可直接访问父模型的字段
- 数据存储在多张表中
"""
_name = 'library.book'
_description = '关联产品模板的图书馆图书'
_inherits = {
'product.template': 'product_tmpl_id'
}
product_tmpl_id = fields.Many2one(
'product.template',
string="关联产品",
required=True,
ondelete='cascade',
help="将图书与产品模板记录关联。"
)
author = fields.Char(
string="作者",
help="图书作者姓名。",
required=True,
index=True,
)
isbn = fields.Char(
string="ISBN编号",
help="图书唯一标识。",
copy=False,
index=True,
)
经典继承示例
python
class Inheritance0(models.Model):
_name = 'inheritance.0'
_description = '基础继承模型'
name = fields.Char()
def call(self):
return self.check("模型 0")
def check(self, s):
return "这是 {} 记录 {}".format(s, self.name)
class Inheritance1(models.Model):
_name = 'inheritance.1'
_inherit = ['inheritance.0']
_description = '扩展继承模型'
def call(self):
return self.check("模型 1")
总结
掌握这些模型属性,你就能创建不仅功能完善,而且经过性能优化、安全可靠、用户友好的模型。每个属性都在 Odoo 应用架构中承担特定作用------从赋予模型身份的 _name,到优化复杂场景性能的高级属性 _depends。
在 Odoo 19 中,模型属性远不止基础配置那么简单,它们能将普通的 Python 类转化为功能完整的业务组件。无论你是添加简单的自定义字段,还是设计跨多公司的复杂架构,理解这些属性都能为你提供构建可靠、可扩展解决方案所需的控制力和灵活性。
随着 Odoo 开发经验的积累,你会发现这些属性不仅仅是技术细节------它们是真实业务流程在系统中落地的基础。无论是小型企业还是大型集团,每一次流畅的 Odoo 项目实施,背后都离不开对这些模型属性的精准、合理运用。