news 2026/4/16 10:16:31

如何在 Odoo 19 中为自定义模块添加章节和备注

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何在 Odoo 19 中为自定义模块添加章节和备注

如何在 Odoo 19 中为自定义模块添加章节和备注

在 Odoo 中,One2many 字段支持添加章节(Section) 和备注(Note),这两类元素可帮助用户将相关记录分组到有意义的类别中,其中备注还能用于在特定记录的上下文中补充额外信息或说明。例如,在销售订单行中,用户可通过章节和备注更好地组织与管理商品条目。

本文将介绍如何在自定义模型中添加章节和备注功能。操作流程将从创建新模型并添加 One2many 字段开始,逐步完成配置。

一、创建核心模型(Python 代码)

首先需定义两个关联模型:warranty.request(保修申请主模型)和 warranty.request.line(保修申请明细行模型,用于承载章节、备注及商品信息)。

1. 保修申请主模型(warranty.request)

该模型存储保修申请的核心信息(如客户、日期、状态等),并通过 One2many 字段关联明细行。

fromodooimportmodels,fields,_fromdatetimeimportdatetimeclassWarrantyRequest(models.Model):_name='warranty.request'# 模型名称:保修申请_description='Warranty Request'# 模型描述:保修申请_inherit=['mail.thread','mail.activity.mixin']# 继承消息跟踪、活动混合类(支持消息通知)partner_id=fields.Many2one('res.partner',string='客户')# 关联客户模型date=fields.Date(string='申请日期',default=datetime.today())# 申请日期,默认当前日期name=fields.Char(string="序列号",readonly=True,required=True,copy=False,default=_('New'))# 默认值为“New”,后续可通过序列自动生成state=fields.Selection([('draft','草稿'),('to_approve','待审批'),('approved','已审批'),('cancelled','已取消')],string='状态',default='draft',clickable=True)# 状态字段可点击切换warranty_period=fields.Selection([('3months','3 个月'),('6month','6 个月'),('1year','1 年')],string='保修期限',default='3months')warranty_expire_date=fields.Date(string="保修到期日")# 保修到期日期warranty_line_ids=fields.One2many('warranty.request.line',# 关联的明细行模型'warranty_id'# 明细行中关联主模型的字段)description=fields.Html(string='申请说明')# 富文本格式的申请说明

2.保修申请明细行模型(warranty.request.line)

该模型是实现 “章节 / 备注” 功能的核心,需包含 display_type 字段(用于区分 “章节”“备注” 或 “普通商品行”),并通过业务逻辑和 SQL 约束确保数据合法性。

fromodooimport_,api,fields,modelsfromodoo.exceptionsimportUserErrorclassWarrantyRequestLine(models.Model):_name="warranty.request.line"# 模型名称:保修申请明细行_order='warranty_id, sequence, id'# 排序规则:先按主模型ID,再按序号,最后按明细行ID# SQL约束:确保数据完整性_sql_constraints=[# 约束1:需核算行(普通商品行)必须填写必填字段('accountable_required_fields',"CHECK(display_type IS NOT NULL OR (product_id IS NOT NULL AND product_uom_qty IS NOT NULL))","需核算的保修申请明细行缺少必填字段(商品或数量)。"),# 约束2:非核算行(章节/备注)禁止填写商品和数量('non_accountable_null_fields',"CHECK(display_type IS NULL OR (product_id IS NULL AND product_uom_qty = 0))","非核算的保修申请明细行(章节/备注)禁止填写商品或数量。"),]warranty_id=fields.Many2one('warranty.request')# 关联保修申请主模型(反向关联字段)sequence=fields.Integer(string="序号",help="显示保修申请明细行列表时的排序序号",default=10)# 默认序号为10product_id=fields.Many2one('product.product',check_company=True)# 检查商品所属公司与当前环境公司一致name=fields.Text(string="描述",translate=True)# translate=True:支持多语言翻译product_uom_id=fields.Many2one('uom.uom','计量单位',compute='_compute_product_uom_id',store=True,readonly=False,precompute=True)# precompute=True:预计算(提升性能)product_uom_qty=fields.Float(string='数量',required=True,digits='Product Unit of Measure',# 采用商品计量单位的精度配置default=1)display_type=fields.Selection([('line_section',"章节"),('line_note',"备注")],default=False)# 默认无类型(即普通商品行)# 计算字段逻辑:根据商品自动获取计量单位@api.depends('product_id')def_compute_product_uom_id(self):forlineinself:line.product_uom_id=line.product_id.uom_id# 重写创建方法:确保章节/备注行不包含商品和数量信息@api.model_create_multidefcreate(self,vals_list):forvalsinvals_list:# 若当前行是章节/备注(display_type有值)ifvals.get('display_type',self.default_get(['display_type'])['display_type']):# 强制清空商品、数量、计量单位字段vals.update(product_id=False,product_uom_qty=0,product_uom_id=False)returnsuper().create(vals_list)# 重写写入方法:禁止修改行类型(章节/备注/普通行之间不可切换)defwrite(self,values):# 若修改了display_type,且存在行的原类型与新类型不一致if'display_type'invaluesandself.filtered(lambdaline:line.display_type!=values.get('display_type')):raiseUserError(_("无法修改保修申请明细行的类型。请删除当前行,重新创建对应类型的行。"))returnsuper().write(values)

二、配置视图(XML 代码)

需通过 XML 定义主模型的表单视图,重点为 One2many 字段(warranty_line_ids)配置章节与备注专用组件(section_and_note_one2many 组件),并添加 “添加产品”“添加章节”“添加备注” 的快捷按钮。

<recordid="warranty_request_form_view"model="ir.ui.view"><fieldname="name">warranty.request.form.view</field><!-- 视图名称 --><fieldname="model">warranty.request</field><!-- 关联的主模型 --><fieldname="arch"type="xml"><form><!-- 表单视图根标签 --><sheet><!-- 表单“工作表”区域(Odoo 标准布局) --><!-- 顶部基础信息分组 --><group><group><fieldname='partner_id'required="True"string="客户"/></group><group><fieldname='date'string="申请日期"/><fieldname='warranty_period'string="保修期限"/><fieldname='warranty_expire_date'string="保修到期日"/></group></group><!-- 标签页区域 --><notebook><!-- 标签1:商品明细(承载章节/备注/商品行) --><pageid="product_page"name="商品明细"><!-- One2many字段:配置章节与备注组件 --><fieldname="warranty_line_ids"widget="section_and_note_one2many"><!-- 明细行列表视图(可编辑,新增行在底部) --><liststring="商品明细行"editable="bottom"><!-- 快捷操作按钮组(添加产品/章节/备注) --><control><createname="add_product_control"string="添加产品"/><!-- 默认创建“章节”行 --><createname="add_section_control"string="添加章节"context="{'default_display_type':'line_section'}"/><!-- 默认创建“备注”行 --><createname="add_note_control"string="添加备注"context="{'default_display_type':'line_note'}"/></control><!-- 隐藏display_type字段(仅用于逻辑判断,不显示给用户) --><fieldname="display_type"column_invisible="True"/><!-- 序号字段(支持拖拽排序) --><fieldname="sequence"widget="handle"/><!-- 商品字段:仅普通行必填(章节/备注行无需填写) --><fieldname="product_id"required="not display_type"string="产品"/><!-- 描述字段(章节/备注的标题/内容,普通行的商品描述) --><fieldname="name"/><!-- 数量字段:仅普通行必填 --><fieldname="product_uom_qty"/><!-- 计量单位字段:仅普通行必填 --><fieldname="product_uom_id"required="not display_type"/></list></field></page><!-- 标签2:申请说明 --><pageid="description_page"name="申请说明"><!-- 富文本说明字段:仅草稿状态可编辑 --><fieldname="description"readonly="state !='draft'"/></page></notebook></sheet><!-- 消息聊天区(支持添加评论、附件等) --><chatter/></form></field></record>

这会产生以下视图:默认情况下,我们会得到“添加行”控制按钮。

三、实现章节与备注的关键步骤

若需在自定义 One2many 模型中支持章节与备注,需严格遵循以下 4 个步骤。

步骤 1:在明细行模型中添加 display_type 字段

在 One2many 关联的明细行模型(如 warranty.request.line)中,必须添加 display_type 选择字段,用于区分行类型(章节 / 备注 / 普通行);同时需添加 name 字段,用于存储章节标题或备注内容:

display_type=fields.Selection([('line_section',"章节"),('line_note',"备注")],default=False)name=fields.Text(string="描述",translate=True)

步骤 2:重写 create 和 write 方法

@api.model_create_multidefcreate(self,vals_list):forvalsinvals_list:ifvals.get('display_type',self.default_get(['display_type'])['display_type']):vals.update(product_id=False,product_uom_qty=0,product_uom_id=False)returnsuper().create(vals_list)

·create 方法:确保创建章节 / 备注行时,自动清空商品(product_id)、数量(product_uom_qty)等核算字段,避免数据冲突。

defwrite(self,values):if'display_type'invaluesandself.filtered(lambdaline:line.display_type!=values.get('display_type')):raiseUserError(_("无法修改保修申请明细行的类型。请删除当前行,重新创建对应类型的行。"))returnsuper().write(values)

·write 方法:禁止修改行类型(如 “章节” 不可改为 “备注” 或 “普通行”),需删除原行后重新创建,保证数据逻辑一致性。

步骤 3:添加 SQL 约束

通过强制规定保修请求行要么是显示行(设置了 display_type),要么是可核算行(设置了 product_id 和 quantity),但不能同时是两者,从而确保数据完整性。

_sql_constraints=[('accountable_required_fields',"CHECK(display_type IS NOT NULL OR (product_id IS NOT NULL AND product_uom_qty IS NOT NULL))","需核算的保修申请明细行缺少必填字段(商品或数量)。"),('non_accountable_null_fields',"CHECK(display_type IS NULL OR (product_id IS NULL AND product_uom_qty = 0))","非核算的保修申请明细行(章节/备注)禁止填写商品或数量。"),]

·non_accountable_null_fields 约束:保证对于设置了 display_type 的行,product_id 必须为空,并且数量必须为零。
·non_accountable_null_fields 约束:确保当设置了 display_type 时,product_id 必须保持为空,并且数量必须设置为零。

步骤 4:在视图中配置组件与控制按钮

1、配置专用组件:为 One2many 字段添加 widget=“section_and_note_one2many”,启用章节与备注的可视化样式(如章节标题加粗、备注行斜体)。

<fieldname="warranty_line_ids"widget="section_and_note_one2many">

2、添加快捷按钮:在 标签内通过 定义 “添加产品”“添加章节”“添加备注” 按钮,并通过 context 预设 display_type 值,实现点击即创建对应类型的行。
这些控件使用户能够快速添加具有为章节和备注预置上下文的新记录。

<control><createname="add_product_control"string="添加产品"/><!-- 默认创建“章节”行 --><createname="add_section_control"string="添加章节"context="{'default_display_type':'line_section'}"/><!-- 默认创建“备注”行 --><createname="add_note_control"string="添加备注"context="{'default_display_type':'line_note'}"/></control>

·产品控件:没有任何特定上下文,这将生成标准的产品行。
·章节控件:默认将 display_type 设置为 “line_section”。
·备注控件:默认将 display_type 设置为 “line_note”。

3、隐藏 display_type 字段:通过 column_invisible=“True” 隐藏该字段,避免用户误操作。

<fieldname="display_type"column_invisible="True"/>

4、动态设置必填规则:为 product_id、product_uom_qty 等字段设置 required=“not display_type”,仅普通行强制必填。

<fieldname="name"/><fieldname="product_uom_qty"/><fieldname="product_uom_id"required="not display_type"/>

确保 product_id 和 quantity 字段仅在未设置 display_type 时为必填。

在 One2many 树形视图中,用户可以添加章节和备注,如下面的截图所示。

四、章节与备注的优势

在 Odoo 中,在 One2Many 字段中使用章节和备注提供了多种优势,可以增强组织性、用户体验和整体效率。章节允许用户在表单或视图中轻松分离和识别不同的类别或数据集,从而提高信息的可读性。同时,备注提供了一种包含与特定记录直接相关的额外细节或评论的方式。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 13:34:01

基于SpringBoot的KPL赛事综合管理系统的设计与实现

KPL赛事综合管理系统课题背景 电子竞技产业近年来发展迅猛&#xff0c;尤其是移动电竞领域&#xff0c;王者荣耀职业联赛&#xff08;KPL&#xff09;作为国内顶级移动电竞赛事&#xff0c;其规模与影响力持续扩大。随着赛事体系日趋复杂&#xff0c;传统人工管理模式已难以应对…

作者头像 李华
网站建设 2026/4/10 16:42:17

基于Hadoop的南昌市房价预测系统的设计与实现开题报告

基于Hadoop的南昌市房价预测系统的设计与实现开题报告 一、研究背景与意义 &#xff08;一&#xff09;研究背景 随着我国房地产市场的持续发展与调控政策的不断深化&#xff0c;房价走势已成为关乎民生福祉、经济稳定与城市发展的核心议题。南昌市作为江西省省会&#xff0c;近…

作者头像 李华
网站建设 2026/4/5 21:20:48

Stable Diffusion Web UI 绘世版 v4.6.1 整合包:一键极速部署,深度解决 AI 绘画环境配置与 CUDA 依赖难题

对于从事 AI 创作或 AIGC 研究的开发者来说&#xff0c;Stable Diffusion (SD) 是目前本地化部署的首选框架。然而&#xff0c;原生环境搭建往往涉及复杂的 Python 虚拟环境管理、CUDA 版本的严格匹配以及大量的 Git 依赖拉取&#xff0c;任何一个环节出错都可能导致部署失败。…

作者头像 李华
网站建设 2026/4/4 6:06:31

张氏相机标定,不求甚解使用篇

本文记录使用张氏标定法进行使用的全过程&#xff0c;并记录最终的误差成果,为什么需要标定是因为相机本身拍照之后&#xff0c;就存在一个畸变&#xff0c;所以仅靠一个比例尺来进行推算实际距离 和 像素距离之间的比例&#xff0c;是存在很大的偏差的&#xff0c;理解一下&am…

作者头像 李华
网站建设 2026/4/3 16:33:01

【课程设计/毕业设计】基于springboot的旅行指南系统整合目的地攻略、行程规划、景点推荐、美食住宿查询、旅行日记分享的设计与实现【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/15 10:29:38

5.Spring Boot、Spring MVC 和 Spring 有什么区别

Spring Boot、Spring MVC 和 Spring 有什么区别Spring是⼀个IOC容器&#xff0c;⽤来管理Bean&#xff0c;使⽤依赖注⼊实现控制反转&#xff0c;可以很⽅便的整合各种框架&#xff0c;提供AOP机制弥补OOP的代码重复问题、更⽅便将不同类不同⽅法中的共同处理抽取成切⾯、⾃动注…

作者头像 李华