从 Owl 2 到 Owl 3
一、Odoo 的前端框架 OWL
你每天在写的 form、list、kanban 视图,聊天、设置中心的每一个面板,底层都是一个个 Owl 组件。组件就是一段自带逻辑和 HTML 模板、可以嵌套复用的界面单位。Owl 是 Odoo 自研的前端组件框架。Odoo 不用 React 或 Vue,是因为 ERP 前端有自己的口味:极小的包体,XML 模板(和后端 QWeb 视图一脉相承),精细的局部更新:一个几万行的表单里改一个字段,只重画那一小块。
共 73 篇文章 · 当前标签「Odoo」
你每天在写的 form、list、kanban 视图,聊天、设置中心的每一个面板,底层都是一个个 Owl 组件。组件就是一段自带逻辑和 HTML 模板、可以嵌套复用的界面单位。Owl 是 Odoo 自研的前端组件框架。Odoo 不用 React 或 Vue,是因为 ERP 前端有自己的口味:极小的包体,XML 模板(和后端 QWeb 视图一脉相承),精细的局部更新:一个几万行的表单里改一个字段,只重画那一小块。
写 Odoo 代码时,最多的两件事是:这个模型上有哪些字段,和这个方法是谁加进来的。普通 Python 工具对这两件事一无所知 —— 因为 Odoo 的扩展模型不是直接通过Python类继承获得的,而是运行时拼出来的。我们在扩展模型中无法定位被扩展模型上定义的变量和方法。
Odoo 的模型是运行时拼装出来的:一个模型由多个 addon 通过 _inherit 不断扩展,最后在 registry 里合成。这带来一个副作用——静态类型检查器看不见它。
Python 的类型检查器(Pyright、mypy)靠继承关系推断类型。但 Odoo 扩展模型并不靠 Python 继承:
class CrmLead(models.Model):
_inherit = "crm.lead"
@api.model
def attach_source(self, partner_id: int, source: str) -> None:
...
在检查器眼里,env["crm.lead"] 的类型永远是 BaseModel:它不知道这个模型上还有什么方法。
于是你想调用别处加进来的方法时,编辑器只能这样报错:
class ResPartner(models.Model):
_inherit = "res.partner"
def action_mark_referral(self) -> None:
leads = self.env["crm.lead"]
leads.attach_source(partner_id=self.id, source="referral")
# Pyright: Cannot access member "attach_source" for type "BaseModel"
⚠️ 关键在这条报错的含义:它不是说方法不存在,而是检查器不知道这个模型上有什么。
于是你既得不到补全,也得不到校验——写错参数名、传错类型,它都不会提醒你,只能整段 # type: ignore 掉。
如果你想再进一步,用 Protocol 去约束"服务层需要的模型接口",也同样做不到:检查器无法确认运行期拿到的模型实例真的满足那个接口。
Odoo 20 发布后,官方宣传里 AI 占了很大篇幅。营销归营销,我们把 20.0 的源码翻了一遍,对照 19.0,从代码层面看 AI 到底变了什么。先说清楚取材范围:社区版(odoo/odoo)两个大版本里都没有 ai 模块,产品化的 AI 功能几乎全部在企业版(odoo/enterprise)。所以本文的主战场是企业版,社区版只讲框架层的配套变化。
本文的 20 条新特性来自 Odoo 官方在 2026 年 4 月 2 日 Partner Days 上发布的 Odoo 20 路线图。发布节奏如下,新版本将在 9 月 24-26 日的 Odoo Experience 布鲁塞尔大会 期间正式发布。
按照商业授权的不同Odoo的版本可分为:“社区版”和“企业版”。社区版提供了Odoo的整体框架和核心功能,企业版以社区版为核心提供一系列的企业专属增强模块来扩展社区版的功能并包含企业专属服务。社区版的代码公开发布在Github上: http://www.github.com/odoo/odoo ,可自由获取。企业版的代码在获得商业授权后,由Odoo公司或Odoo授权合作伙伴提供。根据Odoo官方的说明,为确保Odoo开源社区版本的竞争力,其在社区版和企业版的研发投入比例是80%之于20%。 下图说明了社区版和企业版的区别:
在模块开发中,我们往往会引入第三方的python模块。比如当我们在对业务数据做统计分析时,可能会用到pandas Python函数库。在开发者这边我们可以安装pandas包,然后就可以在Odoo模块代码中导入pandas包中的函数,类等:
其实把Odoo换成“一切”也可以。因为正如李普曼在《Public Opinion》里所说:“多数情况下我们并不是先理解后定义,而是先定义后理解。我们往往只能看到自己所熟悉、所喜欢的景象,那些与之相抵触的事实则会视而不见,而这自然就构成了我们认知的“刻板印象”(Sterotype)。当然我们这里毕竟不是来探讨哲学,社会学命题的,而是想跟大家聊聊Odoo相关的一些“刻板印象”。
十月四号,Odoo公司发布了最新的Odoo12版本。首先来看看这次发布会上的亮眼功能。
Odoo系统中主要包含下面三类按钮, 见下图:
普通按钮
布尔按钮: 参见之前的介绍
动态按钮
[!NOTE] 也有人将Odoo的Smart Button直译为“智能按钮”的,感觉稍显夸张。另外,布尔按钮实际上也是一种特殊的动态按钮。