文章目录
- @[toc]
- Odoo 18 ORM 深度解析
- 🧠 一句话总结 Odoo ORM 原理
- 🧱 ORM 核心结构概览
- 🔄 ORM 生命周期与原理分析
- 1️⃣ 模型定义(Python class)
- 2️⃣ 模型注册(MetaModel & Registry)
- 3️⃣ 数据库表创建(自动同步)
- 4️⃣ CRUD 操作流程
- 📝 以 `create()` 为例:
- 🧩 CRUD 源码实现深度分析
- 5️⃣ 多记录操作的支持:`recordset` 机制
- 6️⃣ 计算字段机制(@api.depends)
- 7️⃣ 缓存机制(ORM 缓存)
- 8️⃣ 权限校验机制
- 🧰 ORM 特性总结表
- 🔄 ORM 实现图(简略)
- ✅ 总结一句话
- 🧩 ORM 技术深度解读
- 1. 元编程与元类机制
- 2. 字段类型与高级特性
- 3. 环境(env)与上下文机制
- 4. 事务与一致性保障
- 5. 性能优化机制
- 6. 安全与权限体系
- 7. 扩展性与自定义能力
- 8. 与外部系统集成
- 9. 典型源码流程图
- 10. 常见开发/调试技巧
文章目录
- @[toc]
- Odoo 18 ORM 深度解析
- 🧠 一句话总结 Odoo ORM 原理
- 🧱 ORM 核心结构概览
- 🔄 ORM 生命周期与原理分析
- 1️⃣ 模型定义(Python class)
- 2️⃣ 模型注册(MetaModel & Registry)
- 3️⃣ 数据库表创建(自动同步)
- 4️⃣ CRUD 操作流程
- 📝 以 `create()` 为例:
- 🧩 CRUD 源码实现深度分析
- 5️⃣ 多记录操作的支持:`recordset` 机制
- 6️⃣ 计算字段机制(@api.depends)
- 7️⃣ 缓存机制(ORM 缓存)
- 8️⃣ 权限校验机制
- 🧰 ORM 特性总结表
- 🔄 ORM 实现图(简略)
- ✅ 总结一句话
- 🧩 ORM 技术深度解读
- 1. 元编程与元类机制
- 2. 字段类型与高级特性
- 3. 环境(env)与上下文机制
- 4. 事务与一致性保障
- 5. 性能优化机制
- 6. 安全与权限体系
- 7. 扩展性与自定义能力
- 8. 与外部系统集成
- 9. 典型源码流程图
- 10. 常见开发/调试技巧
Odoo 18 ORM 深度解析
Odoo 18 的 ORM(对象关系映射)是其最核心的部分之一,承担着模型定义、数据库操作、业务逻辑执行、权限控制、缓存机制等关键功能。Odoo ORM 通过 Python 类定义模型(Model),自动映射为 PostgreSQL 表,并借助丰富的装饰器、钩子和缓存机制实现功能增强。
🧠 一句话总结 Odoo ORM 原理
基于 Python 类、元编程和元模型注册机制,自动将类映射为 PostgreSQL 表,并提供统一的 CRUD、规则验证、上下文环境、事务控制与缓存优化的操作接口。
🧱 ORM 核心结构概览
odoo/
├── models/
│ ├── base.py # Model 基类,注册/字段定义/元类处理
│ ├── fields.py # 所有字段类型定义,如 Char、Many2one、One2many
│ ├── model.py # 核心模型类 Model 的实现
│ ├── registry.py # 注册表:管理所有模型类及数据库连接
│ ├── crud.py # 实际执行 CRUD 操作的底层实现
│ ├── osv/
│ │ ├── orm.py # 兼容老版本 osv API 的适配层
│ └── ...
🔄 ORM 生命周期与原理分析
1️⃣ 模型定义(Python class)
开发者通过如下方式定义模型:
class ResPartner(models.Model):_name = "res.partner"name = fields.Char()active = fields.Boolean(default=True)
背后过程:
- 所有模型继承自
odoo.models.Model
- 使用元类
MetaModel
拦截类定义,抽取_name
和字段定义,并注册到Registry
- 字段通过
fields.*
类定义(如Char
,Boolean
等),每个字段在内存中表示为Field
实例,带有required
,readonly
,compute
,inverse
等属性
2️⃣ 模型注册(MetaModel & Registry)
# odoo.models.base.MetaModel
class MetaModel(type):def __new__(mcs, name, bases, attrs):# 收集字段、约束等元信息...# 注册模型到环境的注册表中cls = super().__new__(...)registry.register_model(cls)
# odoo.modules.registry.Registry
class Registry:def __init__(self, dbname):self.models = {} # 存储所有模型...
3️⃣ 数据库表创建(自动同步)
安装模块时,Odoo 根据模型结构调用 tools.convert.convert_xml_import()
自动创建数据库表结构。
4️⃣ CRUD 操作流程
📝 以 create()
为例:
partner = self.env['res.partner'].create({'name': 'Tom'})
实际流程:
- 入口方法为
Model.create()
:def create(self, vals):self._check_create_rights()self._validate_fields(vals)...ids = self._create(vals)return self.browse(ids)
- 核心创建逻辑在
_create()
方法中,通过cr.execute
直接写入数据库 - 自动计算字段、约束校验、触发
@api.onchange
,@api.model_create_multi
,@api.constrains
等钩子
🧩 CRUD 源码实现深度分析
Odoo ORM 的 CRUD(增删改查)操作不仅仅是 SQL 封装,还集成了权限校验、字段校验、钩子机制、批量优化、懒加载和缓存等多重机制。以 create()
为例,源码实现流程如下:
1. 统一入口:
所有模型都继承自 odoo.models.Model
,开发者通过 self.env['model.name'].create(vals)
等方式调用 CRUD 方法。
2. create() 方法源码流程:
def create(self, vals):self._check_create_rights()self._validate_fields(vals)...ids = self._create(vals)return self.browse(ids)
- 权限校验:
_check_create_rights()
检查当前用户是否有创建权限 - 字段校验:
_validate_fields(vals)
检查必填、只读、类型等约束 - 核心写入:
_create(vals)
负责实际的数据库插入,底层通过cr.execute
生成 SQL - 钩子机制:自动触发
@api.onchange
,@api.model_create_multi
,@api.constrains
等装饰器方法 - 返回值:始终返回一个 recordset(即使只创建一条记录)
3. write()、unlink()、search() 实现:
- write(vals):批量更新,先校验权限和字段,再通过
cr.execute
生成 UPDATE SQL,支持批量操作和自动触发相关钩子 - unlink():删除操作,先校验权限和规则,再通过
cr.execute
生成 DELETE SQL,支持级联删除和钩子 - search(domain):查询操作,domain 转为 SQL WHERE,支持复杂条件、分页、排序,返回 recordset
4. 底层实现与优化:
- 底层 SQL 执行:所有 CRUD 最终都通过
self.env.cr.execute(sql, params)
与 PostgreSQL 交互 - 批量优化:Odoo 会自动将多条操作合并为一条 SQL,减少 N+1 问题
- 懒加载:recordset 只在访问字段时才真正查询数据库
- 缓存机制:常用查询和字段值会被缓存,减少数据库压力
5. 权限与规则:
- 每次 CRUD 前都会自动调用
_check_access_rights
(模型级)、_check_record_rules
(记录级)、_check_company
(多公司)等方法,保证数据安全
6. 钩子与扩展:
- 支持
@api.depends
、@api.onchange
、@api.constrains
等装饰器,开发者可自定义业务逻辑 - 支持多种继承和 mixin,便于扩展和重载 CRUD 行为
7. 典型源码调用链(以 create 为例):
self.env['res.partner'].create(vals)
- 进入
Model.create()
(odoo/models/model.py) - 权限校验、字段校验
- 调用
_create()
,底层cr.execute(INSERT ...)
- 触发相关钩子
- 返回
self.browse(ids)
,即 recordset
5️⃣ 多记录操作的支持:recordset
机制
Odoo 的 ORM 是 “记录集优先” 的,即使只有一条记录,API 也始终返回一个 recordset。
# 多记录统一调用写操作
partners = self.env['res.partner'].browse([1, 2, 3])
partners.write({'active': False})
Recordset 是一个可迭代对象,封装了 ID 列表与当前环境 (env
),具备懒加载、批处理优化等特性。
6️⃣ 计算字段机制(@api.depends)
total = fields.Float(compute='_compute_total')@api.depends('amount', 'tax')
def _compute_total(self):for rec in self:rec.total = rec.amount + rec.tax
ORM 会自动根据依赖关系构建计算图,仅在相关字段变化时重新计算。
7️⃣ 缓存机制(ORM 缓存)
结合 odoo.tools.cache
模块的 @ormcache
实现自动缓存函数结果,如:
@ormcache('self.env.uid')
def get_partner_count(self):...
字段值、recordset 本身也存在内存中做延迟加载(lazy load)。
8️⃣ 权限校验机制
CRUD 操作前调用权限方法:
_check_access_rights
_check_record_rules
_check_company
(多公司支持)
支持从 UI、RPC、XML-RPC 层自动传入用户上下文校验。
🧰 ORM 特性总结表
特性 | 描述 | 相关源码模块 |
---|---|---|
模型注册 | 所有模型通过元类注册 | base.py , registry.py |
字段定义 | 字段类封装类型与属性 | fields.py |
多记录集支持 | RecordSet 实现统一操作 | model.py |
动态计算 | 支持 @api.depends 自动刷新 | api.py |
数据校验 | _check_* , @constrains 机制 | model.py |
缓存优化 | @ormcache , record cache | tools/cache.py |
安全校验 | 权限 + 规则双重验证 | access.py , rules.py |
多语言支持 | 字段翻译机制 | translate.py |
上下文传递 | self.env 携带上下文 | api.py |
多公司机制 | company_dependent , check_company | fields.py , model.py |
🔄 ORM 实现图(简略)
┌───────────────┐
│ Python 模型类 │
└───────┬───────┘│▼MetaModel│▼注册表 Registry│▼数据库表映射│▼字段类型 (fields.X)│▼CRUD 方法封装 (create/write/browse/search)│▼权限 + 缓存 + 依赖 + API 修饰器│▼PostgreSQL 数据库
✅ 总结一句话
Odoo ORM 是围绕"声明式模型 + 元编程注册 + 懒加载记录集 + 事务安全 + 上下文感知"的强大抽象层,它屏蔽了 SQL 细节,统一了数据与业务操作,极大提升了企业级开发的效率与安全性。
🧩 ORM 技术深度解读
1. 元编程与元类机制
Odoo ORM 的核心在于 Python 的元类(MetaModel),它不仅负责模型注册,还实现了字段收集、继承链处理、自动生成 SQL 映射等。
- 字段收集与继承:MetaModel 会递归父类,合并所有字段定义,支持多重继承和字段重载。
- 自动生成表结构:通过分析
_name
、字段类型、约束等,自动生成 PostgreSQL 的表结构和索引。 - 模型生命周期钩子:如
__init__
,__new__
,__setup__
,用于模型初始化和扩展。
2. 字段类型与高级特性
- 关系字段:如
Many2one
,One2many
,Many2many
,自动处理外键、联表、级联删除等。 - 动态属性:如
compute
,inverse
,search
,related
,实现自动计算、反向写入、自定义搜索等。 - 字段扩展:支持
selection
,context_dependent
,company_dependent
等高级特性。
3. 环境(env)与上下文机制
self.env
是 Odoo ORM 的"上下文载体",包含当前用户、公司、语言、事务等信息。- 支持多数据库(多租户)、多公司、动态上下文切换,保证数据隔离与权限安全。
4. 事务与一致性保障
- 所有操作都在 PostgreSQL 事务中执行,支持自动回滚、嵌套事务(savepoint)、乐观锁等。
- 支持
@api.autovacuum
,@api.model_cr
等钩子,自动维护数据一致性和表结构升级。
5. 性能优化机制
- 延迟加载(Lazy Load):Recordset 只在访问字段时才查询数据库,避免不必要的 SQL。
- 批量操作优化:如
write
,unlink
支持批量 SQL,减少循环和 N+1 查询。 - 缓存机制:
@ormcache
支持参数化缓存,字段值缓存,减少重复计算和数据库访问。
6. 安全与权限体系
- 多层权限校验:模型级(access rights)、记录级(record rules)、字段级(field access)、公司级(multi-company)。
- 上下文感知:权限校验自动感知当前用户、公司、上下文,支持自定义规则和动态调整。
7. 扩展性与自定义能力
- 支持通过继承(_inherit)、mixin、装饰器(@api.model, @api.depends, @api.constrains)等方式灵活扩展模型和业务逻辑。
- 支持模块化开发,模型和字段可被多个模块动态扩展和重载。
8. 与外部系统集成
- ORM 屏蔽了 SQL 细节,支持通过 RPC、XML-RPC、JSON-RPC、REST API 等多种方式与外部系统交互。
- 支持自动序列化、反序列化、权限校验和上下文传递。
9. 典型源码流程图
flowchart TDA -->Python模型类MyModel(models.Model) --> B[MetaModel元类字段/元信息收集]B --> C[注册表 Registry模型注册/管理]C --> D[数据库表映射自动建表/同步]D --> E[CRUD方法封装create/write/search/unlink]E --> F[权限校验_check_access_rights/_check_record_rules]E --> G[缓存机制 @ormcache/懒加载]E --> H[依赖与钩子 @api.depends/@api.onchange]F --> I[PostgreSQL数据库]G --> IH --> I
10. 常见开发/调试技巧
- 使用
self.env.cr
直接执行 SQL 以优化特殊场景。 - 利用
@api.model_create_multi
优化批量创建性能。 - 善用
@api.depends
精确声明依赖,避免不必要的计算。 - 通过
sudo()
、with_context()
、with_company()
灵活切换权限和上下文。