第7讲、Odoo 18 源码深度分析

article/2025/8/26 13:02:15

Odoo 作为全球知名的开源 ERP 系统,其底层架构由众多核心 Python 文件共同支撑。本文将围绕 Odoo 18 版本中 的 api.py、exceptions.py、fields.py、http.py、loglevels.py、models.py、netsvc.py、release.py、sql_db.py 等关键文件,进行源码结构与实现机制的系统性解读,帮助开发者深入理解 Odoo 的设计思想与技术细节。

1. models.py —— ORM 的核心引擎

models.py 是 Odoo ORM 的核心实现,负责对象关系映射、模型注册、继承机制、字段管理、缓存、权限校验等关键功能。主要内容包括:


models.py 深度解读 —— Odoo ORM 的灵魂

Odoo 的 models.py 文件是其 ORM(对象关系映射)系统的核心,实现了模型的定义、继承、注册、字段管理、数据操作、权限校验等一系列复杂而强大的功能。理解 models.py,是深入掌握 Odoo 二次开发和底层机制的关键。

1. MetaModel —— 元类与模型注册

Odoo 采用了 Python 的元类(MetaModel)机制来实现模型的自动注册和元数据管理。每当你定义一个继承自 ModelAbstractModel 的类时,MetaModel 会自动:

  • 注册模型到全局模型池,便于后续通过 env['model.name'] 动态访问。
  • 处理模型的继承链(_inherit_inherits),支持多继承和委托继承。
  • 自动为模型添加魔法字段(如 id, create_date, write_uid 等),保证所有模型具备统一的基础属性。
  • 维护模型与模块的映射关系,便于模块化开发和模型隔离。

用法案例:MetaModel 的作用是自动注册模型,开发者无需直接使用,但其效果体现在所有模型定义中。

# 只需继承 models.Model,MetaModel 会自动注册模型
class LibraryBook(models.Model):_name = 'library.book'name = fields.Char(string='Book Name')
2. BaseModel、Model、AbstractModel —— 模型基类体系
  • BaseModel:所有 Odoo 模型的基类,定义了 ORM 的核心方法和属性,如 _fields(字段字典)、_name(模型名)、_order(默认排序)、_auto(是否自动建表)等。它还实现了数据的增删改查(CRUD)、缓存、权限校验、上下文管理等底层逻辑。

用法案例:BaseModel 通常不直接被开发者使用,但可以通过继承自定义特殊用途的基类。

from odoo.models import BaseModelclass MyBase(BaseModel):_name = 'my.base'_abstract = True# 可在此定义通用方法供子类继承
  • Model:用于持久化(有数据库表)的业务模型,开发者自定义的模型通常继承自它。

用法案例:

class ResPartner(models.Model):_name = 'res.partner'name = fields.Char(required=True)email = fields.Char()
  • AbstractModel:抽象模型,不会在数据库中创建表,常用于定义可复用的行为或接口。

用法案例:

class MailThread(models.AbstractModel):_name = 'mail.thread'_description = 'Threaded Emails'# 可定义通用行为供其他模型继承

亮点
Odoo 通过区分持久化模型和抽象模型,支持灵活的代码复用和多层次的业务抽象。

3. 字段管理与多继承机制
  • 所有模型字段都通过 _fields 属性进行统一管理,支持多种类型(普通字段、关系字段、计算字段等)。
  • 支持字段的继承与重载:在多继承场景下,字段定义会被合并,参数自动叠加或覆盖,保证模型扩展的灵活性。
  • 字段的定义和 setup 过程高度自动化,支持默认值、只读、必填、索引、唯一约束等丰富属性。

亮点
字段的自动合并和 setup 机制,使得 Odoo 的模型扩展和模块协作变得异常强大和灵活。

4. ORM 操作与缓存机制
  • 提供了丰富的 ORM 操作方法,如 searchcreatewriteunlinkreadbrowse 等,支持链式调用和批量操作。
  • 内置多级缓存(如字段缓存、记录缓存、方法缓存),大幅提升了数据访问性能。
  • 支持懒加载、预取(prefetch)、脏数据检测等优化手段,保证高并发下的数据一致性和效率。

亮点
Odoo 的 ORM 不仅语法优雅,还兼顾了性能和一致性,适合大规模企业级应用。

5. 权限与约束校验
  • 内置了细粒度的权限校验机制(如 check_access_rightscheck_access_rule),支持按用户、组、记录级别的访问控制。
  • 支持声明式约束(如 SQL 约束、Python 约束、唯一性约束等),保证数据的完整性和业务规则的强制执行。
6. 继承机制:_inherit 与 _inherits
  • _inherit:类继承,允许多个模型通过 Python 继承链扩展同一个模型,常用于功能叠加和行为扩展。
  • _inherits:委托继承,允许一个模型"委托"另一个模型的字段,实现类似"组合"的效果,常用于复合业务场景。

亮点
双重继承机制让 Odoo 的模型扩展既可以"加行为",也可以"加结构",极大提升了系统的可塑性。

7. 魔法字段与元数据
  • Odoo 自动为每个模型添加一系列"魔法字段",如 idcreate_uidcreate_datewrite_uidwrite_date 等,方便追踪数据的创建和修改历史。
  • 支持模型元数据的动态生成和管理,便于后续的自动化工具和元编程。
8. 典型代码片段举例
class ResPartner(models.Model):_name = 'res.partner'_description = 'Contact'name = fields.Char(required=True)email = fields.Char()is_company = fields.Boolean()parent_id = fields.Many2one('res.partner', string='Parent')# 计算字段display_name = fields.Char(compute='_compute_display_name')@api.depends('name', 'parent_id')def _compute_display_name(self):for rec in self:rec.display_name = f"{rec.name} ({rec.parent_id.name})" if rec.parent_id else rec.name

2. fields.py —— 字段类型与属性管理


fields.py 深度解读 —— Odoo 字段系统的基石

Odoo 的 fields.py 文件是其 ORM 字段系统的核心,实现了字段类型的定义、属性管理、继承与重载、计算与相关字段等机制。理解 fields.py,有助于掌握 Odoo 数据建模的精髓。

1. Field 基类与字段属性
  • Field 是所有字段类型的基类,定义了字段的核心属性(如 nametypemodel_namestoreindexrequireddefault 等)。
  • 字段的初始化和 setup 机制,支持多继承下的字段合并与重载。
  • 字段对象本身是描述符,负责管理字段在模型类和实例上的访问逻辑。

亮点
字段基类高度抽象,支持灵活的参数扩展和属性管理,是 Odoo 字段系统的基础。

2. 丰富的字段类型
  • Odoo 内置了丰富的字段类型,包括:
    • 基础类型CharTextIntegerFloatBooleanDateDatetime 等。
    • 关系类型Many2oneOne2manyMany2many,用于模型间的多种关联关系。
    • 选择类型Selection,用于枚举值选择。
    • 特殊类型:如 BinaryHtmlMonetary 等,满足多样化业务需求。

亮点
字段类型的多样性和可扩展性,使 Odoo 能灵活适配各种业务场景。

3. 字段继承与重载机制
  • 支持字段在多继承场景下的合并与重定义,参数自动叠加或覆盖,保证模型扩展的灵活性。
  • 字段 setup 机制会根据继承链自动处理字段属性的合并与覆盖。
  • 字段的 _base_fields 属性记录了所有继承链上的字段定义,便于后续合并。

亮点
自动合并和重载机制让模块间字段扩展变得简单高效。

4. 计算字段与相关字段
  • 计算字段(compute):通过 compute 参数和 @api.depends 装饰器声明依赖,实现字段值的自动计算。
  • 相关字段(related):通过 related 参数实现跨模型字段的只读引用或同步。
  • 支持计算字段的存储(store=True)、只读、反向写入(inverse)等高级特性。

亮点
声明式的计算与相关字段机制,极大提升了数据一致性和业务建模能力。

5. 字段 setup 机制
  • 字段的 __set_name__ 方法在模型类创建时自动调用,完成字段的注册、属性赋值、参数合并等操作。
  • 支持字段的自动共享、内存优化和 setup 后参数的释放,提升系统性能。
6. 典型代码片段举例
class SaleOrder(models.Model):_name = 'sale.order'_description = 'Sales Order'name = fields.Char(required=True, default='New')date_order = fields.Datetime(string='Order Date', default=fields.Datetime.now)partner_id = fields.Many2one('res.partner', string='Customer', required=True)amount_total = fields.Float(compute='_compute_amount_total', store=True)state = fields.Selection([('draft', 'Draft'),('sent', 'Quotation Sent'),('sale', 'Sales Order'),('done', 'Locked'),('cancel', 'Cancelled'),], default='draft', string='Status')@api.depends('order_line.price_total')def _compute_amount_total(self):for order in self:order.amount_total = sum(line.price_total for line in order.order_line)

3. api.py —— ORM API 与装饰器体系


api.py 深度解读 —— Odoo ORM 的智能接口

Odoo 的 api.py 文件是 ORM 层的"智能接口",为模型方法提供了丰富的装饰器、环境上下文管理、依赖声明和类型定义等机制。理解 api.py,有助于写出高效、优雅、易维护的 Odoo 业务代码。

1. Environment —— 环境对象
  • Environment 类是 Odoo ORM 的上下文载体,封装了数据库游标、当前用户、上下文(context)、模型注册表等信息。
  • 通过 self.env,开发者可以方便地访问当前环境下的各种资源,如 self.env['res.partner'] 获取模型,self.env.user 获取当前用户。
  • 支持多环境并发,保证多用户/多数据库场景下的数据隔离和安全。
  • 提供了如 langcompany_idcr(游标)、user_id 等常用属性,便于多语言、多公司、多用户开发。

亮点
环境对象极大简化了 ORM 操作的上下文管理,让代码更具声明性和可移植性。

2. 装饰器体系
  • Odoo 提供了丰富的 API 装饰器,包括:
    • @api.model:声明方法为模型方法(无 self 记录集,直接操作模型类)。
    • @api.multi(18 版本已废弃,统一为 recordset 方法)。
    • @api.depends:声明计算字段的依赖字段,自动追踪依赖变化。
    • @api.constrains:声明字段约束,自动在写入时校验。
    • @api.onchange:声明前端表单变更时自动触发的方法。
    • @api.returns:声明方法返回类型,便于类型检查和链式调用。
  • 装饰器底层通过元编程,将方法注册到模型元数据中,实现自动依赖追踪、校验和触发。

亮点
装饰器机制让业务逻辑与元数据解耦,极大提升了开发效率和代码可维护性。

3. 依赖与约束声明
  • @api.depends 支持多字段、多层级依赖,自动追踪依赖链,保证计算字段的实时性和一致性。
  • @api.constrains 支持声明式约束,自动在写入时校验业务规则,抛出 ValidationError 即可阻止非法数据写入。
  • @api.onchange 支持前端表单的动态联动,提升用户体验。
4. 类型定义与辅助工具
  • 定义了 DomainTypeContextTypeValuesType 等类型别名,便于类型提示和静态检查。
  • 提供了如 call_kwreturnsconstrains 等辅助函数,增强 API 的灵活性和可扩展性。
5. 典型代码片段举例
class ProductTemplate(models.Model):_name = 'product.template'_description = 'Product'name = fields.Char(required=True)list_price = fields.Float(string='Sales Price')standard_price = fields.Float(string='Cost')margin = fields.Float(compute='_compute_margin', store=True)@api.depends('list_price', 'standard_price')def _compute_margin(self):for product in self:product.margin = product.list_price - product.standard_price@api.constrains('list_price', 'standard_price')def _check_price(self):for product in self:if product.list_price < product.standard_price:raise ValidationError('Sales price cannot be lower than cost!')@api.onchange('list_price')def _onchange_list_price(self):if self.list_price < 0:return {'warning': {'title': 'Warning', 'message': 'Price cannot be negative!'}}

4. http.py —— HTTP 层与控制器机制

http.py 实现了 Odoo 的 HTTP 层,负责 WSGI 应用、请求分发、控制器注册、路由等功能:


http.py 深度解读 —— Odoo Web 框架的中枢

Odoo 的 http.py 文件是其 Web 框架的核心,实现了 HTTP 请求的接收、分发、控制器注册、路由映射、WSGI 兼容等机制。理解 http.py,有助于掌握 Odoo Web 层的扩展与自定义能力。

1. Application —— WSGI 入口与请求分发
  • Application 类实现了 Odoo 的 WSGI 入口,负责 HTTP 请求的接收、预处理、分发和异常处理。
  • 根据请求路径和数据库状态,自动分发到静态资源、无数据库路由或数据库相关路由。
  • 负责请求上下文的创建、异常捕获、日志记录和响应生成。
  • 支持多数据库、多站点环境,适合企业级部署。

亮点
WSGI 兼容设计让 Odoo 可无缝集成到主流 Web 服务器和云平台。

2. Controller 与路由机制
  • Controller 类是所有控制器的基类,@route 装饰器用于声明 URL 路由与处理方法的映射。
  • 支持多级继承和方法重载,允许模块间灵活扩展和复用控制器逻辑。
  • 路由参数支持类型、权限、HTTP 方法等多种声明方式,便于开发 RESTful API 和 Web 页面。
  • 控制器方法可直接返回 HTML、JSON、文件流等多种响应类型。

亮点
控制器和路由机制高度模块化,支持多应用协作和动态扩展。

3. 请求生命周期管理
  • 请求分为静态资源、无数据库请求、数据库请求三大类,分别有独立的处理流程。
  • 支持事务管理、异常捕获、响应序列化、后处理(如注入安全头)等。
  • 集成了权限校验、用户认证、会话管理、CSRF 防护等安全机制。
4. 典型代码片段举例
from odoo import http
from odoo.http import requestclass MyController(http.Controller):@http.route('/hello', type='http', auth='public', website=True)def hello(self, **kw):return "<h1>Hello, Odoo!</h1>"@http.route('/api/data', type='json', auth='user')def api_data(self, **kw):user = request.env.userreturn {'user': user.name, 'id': user.id}

5. 其他工具文件概览

  • exceptions.py:定义了常用的异常类型,如 AccessErrorUserErrorValidationError,用于业务和权限异常的统一处理。

exceptions.py 深度解读 —— Odoo 统一异常与错误处理机制

Odoo 的 exceptions.py 文件为系统和业务开发提供了统一的异常类型,便于在模型、控制器、API 层进行错误抛出、捕获和友好提示。理解异常体系,有助于编写健壮、可维护的 Odoo 应用。

1. 主要异常类
  • UserError:用于业务逻辑错误,通常在用户操作不当时抛出,前端会弹窗提示。
  • AccessError:用于权限校验失败,如无权访问某数据或操作。
  • ValidationError:用于数据校验失败,如字段唯一性、格式等不符合要求。
  • MissingError:用于查找的数据不存在时抛出。
  • AccessDenied:用于认证失败或会话过期等安全场景。
  • CacheMiss:ORM 缓存未命中时的内部异常。
2. 用法与场景
  • 在模型方法、约束、控制器等处主动抛出异常,阻止非法操作并给出明确提示。
  • Odoo 前端会自动捕获这些异常,并以弹窗、警告等方式友好展示给用户。
  • 支持自定义异常消息和参数,便于国际化和上下文提示。
3. 设计亮点
  • 统一的异常体系,便于模块间协作和全局错误处理。
  • 区分业务错误、权限错误、数据错误等,提升系统安全性和用户体验。
  • 支持异常链和详细日志,便于调试和问题追踪。
4. 典型代码片段举例
from odoo.exceptions import UserError, AccessError, ValidationErrorclass SaleOrder(models.Model):_name = 'sale.order'def action_confirm(self):if not self.order_line:raise UserError('订单行不能为空!')if self.env.user.has_group('sale.group_sale_manager') is False:raise AccessError('只有销售经理才能确认订单。')if self.amount_total < 0:raise ValidationError('订单总金额不能为负数。')

总结

整个 Odoo 系统提供了强大的底层支撑。其 ORM、字段管理、API 装饰器、HTTP 控制器等机制,不仅提升了开发效率,也保证了系统的可扩展性和健壮性。深入理解这些源码,



http://www.hkcw.cn/article/daDJMDxxxx.shtml

相关文章

【春秋云镜】CVE-2022-26965 靶场writeup

知识点 网站的主题或者模块位置一般是可以上传文件的&#xff0c;不过一般为压缩包形式主题或者模块可以上github上找到和cms匹配的源码主题被解压后会放到加入到对应的文件夹中&#xff0c;而且还会自动执行对应的info.php文件(需要主题和cms配套才行)我这里取巧了&#xff0…

JUC多线程核心知识点深度解析

最近正在复习Java八股&#xff0c;所以会将一些热门的八股问题&#xff0c;结合ai与自身理解写成博客便于记忆 本文将从以上10个经典面试问题来做juc多线程的解析 一、线程状态与流转机制 1. 六种线程状态&#xff08;Java定义&#xff09; public enum State {NEW, …

设计模式学习笔记

设计模式 一&#xff1a;分类&#xff1a; 创建型模式 用于描述“怎样创建对象”&#xff0c;它的主要特点是“将对象的创建与使用分离”。GoF&#xff08;四人组&#xff09;书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。 结构型模式 用于描述如何将…

【地图】腾讯地图页面卡顿问题解决

目录 背景问题排查解决1. 页面是否使用 keep-alive 进行路由缓存2. 离开地图页面时&#xff0c;是否将地图清除 总结 背景 有的电脑没有显卡会出现如下问题&#xff1a; 系统打开有地图的页面&#xff0c;CPU 占用直线飙升到100%下不来&#xff0c;切到非地图页面&#xff0c;C…

一起看 I/O | Android 性能相关最新动态

作者 / Ben Weiss 过去几年来&#xff0c;我们一直致力于让性能提升工作变得更易上手、回报更高。我们将在本文中分享这一领域的最新发展动态。为您介绍基准配置文件、Android Studio 中的工具改进、库&#xff0c;以及我们如何让这项技术更好地在后台为您服务。此外&#xff0…

iPhone批量删除照片的方法

对于每一个iPhone用户来说&#xff0c;照片管理是一项日常而重要的任务。随着时间的积累&#xff0c;无数的照片快速填满了我们的存储空间&#xff0c;从美丽的风景到重要的家庭聚会&#xff0c;每一张照片都记录着我们生活中的瞬间。然而&#xff0c;当存储空间即将耗尽时&…

Gradle Kotlin 规范插件用于模块化结构 - 共享构建逻辑

Gradle Kotlin 规范插件用于模块化结构 - 共享构建逻辑 我们中的许多人都遇到过Groovy的困难&#xff0c;并习惯于将其转换为Kotlin DSL。 然后&#xff0c;作为Android工程师&#xff0c;在完全使用Kotlin编写的项目上工作是纯粹的喜悦。 我们假设采用基于功能的模块化应用程…

Gradle开发手册-高级篇之多模块项目创建

在进阶篇中详细讲解了gradle配置相关的详细内容。但是是基于单module的配置,在实际开发时基本全是多module类型的项目。所以本章我们就系统学习下如何构建多模块项目(父-子)以及相关的task内容。 基础篇:从概念以及广度上介绍下gradle的核心内容,并构建一个简单的java项目;…

Gradle的版本差异导致无法编译:Could not initialize class com.android.build.gradle.internal.TaskManager

运行项目报错:Could not initialize class com.android.build.gradle.internal.TaskManager 我这边的原因是少了SDK的包和JDK版本不对。 我们先区分下gradle version与gradle plugin version。如果对此不了解&#xff0c;经常会由于Gradle的版本号问题造成项目无法编译&#xf…

Gradle版本目录(Version Catalog)

Gradle版本目录(Version Catalog) “版本目录是一份依赖项列表&#xff0c;以依赖坐标表示&#xff0c;用户在构建脚本中声明依赖项时可以从中选择。” 我们可以使用版本目录将所有依赖项声明及其版本号保存在单个位置。这样&#xff0c;我们可以轻松地在模块和项目之间共享依…

android开发之NDK配置开发

1、打开项目后&#xff0c;一次点击Tools>SDK Manager 2、点击SDK Tools标签页 3、选中NDK&#xff08;Side by Side&#xff09;和CMake复选框 4、点击OK 此时系统会显示一个对话框&#xff0c;告诉你NDK软件包占用了多少磁盘空间 5、点击OK 6、安装完成后&#xff0c;点击…

如何在没有计算机的情况下将联系人从 iPhone 传输到安卓

如果您正在考虑从 iPhone 迁移到Android &#xff0c;您可能想知道如何在不丢失任何重要信息的情况下转移联系人。您可能还想避免使用电脑进行此过程。幸运的是&#xff0c;有几种方法可以教您如何在不使用电脑的情况下将联系人从 iPhone 迁移到Android &#xff0c;而且这些方…

如何将数据从 iPhone 传输到 vivo 的 4 种方法

在运行不同操作系统的 iPhone 和 Vivo 之间传输数据时&#xff0c;需要谨慎。廉价或不安全的在线解决方案可能会失败&#xff0c;并使您的个人数据面临风险。避免被“免费”和“快速”服务的承诺所诱惑&#xff0c;因为这可能会危及您的数据。 在本文中&#xff0c;我们整理了…

图片转换之heic转jpg(使用ImageMagick)

缘由&#xff1a;iphone的图库&#xff0c;用jpg拍照保存后内存占比较大&#xff0c;heic格式会微缩不少。问题来了&#xff0c;电脑不能直接小图预览heic。 分析&#xff1a;现在就是解决小图预览的问题&#xff08;大图用wps可以看&#xff09; 解决&#xff1a;查找了一些…

Android导入项目时Gradle下载速度慢\超时\失败解决方法

Android导入项目时Gradle下载速度慢\超时\失败解决方法 原因分析&#xff1a; 这是因为Gradle源服务器在国外&#xff0c;下载速度自然很慢 distributionUrlhttps\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 解决方法&#xff1a; 最可靠的方法就是换源 &…

从 iPhone 传输到Android 3 种简单方法

使用 iPhone 多年后,也许您想切换到Android并尝试一些新的东西?不管您是否相信,如果您确实做出了这样的决定,您很可能会遇到将数据从 iPhone 传输到Android的问题。由于手机数据对于当今的人们来说非常重要,因此当您切换到另一部手机时丢失它是不明智的。 在本指南中,您…

Contactile三轴触觉力传感器的滑动与摩擦力计算能力

Contactile三轴触觉力传感器通过先进的技术设计&#xff0c;实现了滑动与摩擦力的精准计算。传感器通过分析滑动与振动信号的关联&#xff0c;动态计算摩擦系数&#xff0c;同时捕捉力、扭矩及初始滑动等多维数据。这种能力为机器人提供了高度灵活的触觉反馈&#xff0c;满足复…

国产分子动力学引擎——GPUMD本地部署教程:专为 NVIDIA GPU 加速设计

一、简介 GPUMD 是一款开源分子动力学模拟软件&#xff0c;由渤海大学樊哲勇教授团队主导开发&#xff0c;2017年首发1.0版本&#xff0c;持续迭代至3.9.4版本&#xff0c;是国内首个完全基于GPU加速的开源分子动力学软件&#xff0c;专为 NVIDIA GPU 加速设计。它使用 CUDA 提…

PostgreSQL 备份与恢复策略

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。、 目录 匿名[校招]高级安全工程师(代码审计安全评估) 渗透基础 1. 自我介绍 2. SQL注入写Shell&#xff08;分数…