当前位置: 首页 > web >正文

第8讲、Odoo 18 ORM 深度解析

文章目录

    • @[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'})

实际流程:

  1. 入口方法为 Model.create()
    def create(self, vals):self._check_create_rights()self._validate_fields(vals)...ids = self._create(vals)return self.browse(ids)
    
  2. 核心创建逻辑在 _create() 方法中,通过 cr.execute 直接写入数据库
  3. 自动计算字段、约束校验、触发 @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 为例):

  1. self.env['res.partner'].create(vals)
  2. 进入 Model.create()(odoo/models/model.py)
  3. 权限校验、字段校验
  4. 调用 _create(),底层 cr.execute(INSERT ...)
  5. 触发相关钩子
  6. 返回 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 cachetools/cache.py
安全校验权限 + 规则双重验证access.py, rules.py
多语言支持字段翻译机制translate.py
上下文传递self.env 携带上下文api.py
多公司机制company_dependent, check_companyfields.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() 灵活切换权限和上下文。

http://www.xdnf.cn/news/10194.html

相关文章:

  • AI数字人系统开发——引领未来智能交互潮流
  • C++面试题:Linux系统信号详解
  • Postgre数据库分区生产实战
  • Obsidian 社区插件下载修复
  • 随笔20250530 C# 整合 IC卡读写技术解析与实现
  • LangChain表达式(LCEL)实操案例1
  • C++智能指针介绍和区别(std::unique_ptr、std::shared_ptr 和 std::weak_ptr)
  • 004时装购物系统技术解析:构建智能时尚消费平台
  • PRECICE 工具介绍与使用示例
  • 7.atlas安装
  • 5.30 打卡
  • 【计算机网络】fork()+exec()创建新进程(僵尸进程及孤儿进程)
  • Day40
  • RFID赋能零件智能夹取新生态
  • 深度学习全面掌握指南
  • CMP401GSZ-REEL混合电压接口中的23ns延迟与±6V输入范围设计实现
  • 【Zephyr 系列 2】用 Zephyr 玩转 Arduino UNO / MEGA,实现串口通信与 CLI 命令交互
  • Vue 项目命名规范指南
  • 操作系统原理第9章 磁盘存储器管理 重点内容
  • JAVA:抽象类和接口
  • AI书签管理工具开发全记录(五):后端服务搭建与API实现
  • OSG编译wasm尝试
  • PostgreSQL部署
  • PyCharm接入DeepSeek,实现高效AI编程
  • Python中函数知识详解和示例
  • 正则化-深度学习
  • 2011肠衣问题
  • 视频压制(Video Encoding/Compression)
  • 20250530-C#知识:String与StringBuilder
  • dify账号与基础模型配置