Odoo17中基于回调函数动态设置Many2one字段域的报错排查
Odoo 17扩展res.partner字段失败排查:字段未在数据库创建问题
问题场景
扩展标准res.partner模型,新增settore_principale字段(关联res.partner.industry的Many2one类型),要求该字段可选值的域根据同记录的x_studio_macrocategoria属性动态变化(包括属性修改前后)。现有代码执行后字段未在数据库中创建,触发UndefinedColumn错误。
报错信息
odoo.addons.base.models.ir_qweb.QWebException: Error while render the template UndefinedColumn: column res_partner.settore_principale does not exist LINE 1: ...uid", "res_partner"."write_date" AS "write_date", "res_partn... ^
问题原因
核心问题出在字段定义时的domain参数使用lambda调用实例方法的时机错误:
Odoo在初始化模型、生成数据库表结构阶段,会执行lambda函数。此时self是res.partner模型对象(而非具体记录),调用self._compute_settore_domain()会触发ORM对模型字段的查询,但新字段settore_principale尚未完成创建,导致ORM生成的SQL语句中包含不存在的字段,进而中断字段创建流程。
修复方案
1. 调整域的定义方式
放弃lambda调用实例方法的写法,改用Odoo支持的动态域字符串格式(直接引用当前记录字段),同时保留onchange方法确保字段修改时域实时更新。
2. 确保模型继承正确
确认扩展类正确继承res.partner,并声明_inherit = 'res.partner'。
3. 补充边界处理
在onchange方法中处理x_studio_macrocategoria为空的场景,避免域逻辑出错。
完整修复代码示例
from odoo import models, fields, api class ResPartner(models.Model): _inherit = 'res.partner' settore_principale = fields.Many2one( 'res.partner.industry', string="Settore", # 直接使用动态域字符串,关联当前记录的x_studio_macrocategoria字段 domain="[('x_studio_settore_padre', '=', False), ('x_studio_macrocategoria', '=', x_studio_macrocategoria)]" ) @api.onchange('x_studio_macrocategoria') def _onchange_macrocategoria(self): # 当macrocategoria清空时,重置settore_principale if not self.x_studio_macrocategoria: self.settore_principale = False # 动态生成域,处理macrocategoria为空的情况 domain = [('x_studio_settore_padre', '=', False)] if self.x_studio_macrocategoria: domain.append(('x_studio_macrocategoria', '=', self.x_studio_macrocategoria)) else: # 空值时显示所有顶级行业(或根据需求调整) domain.append(('id', '!=', False)) return {'domain': {'settore_principale': domain}}
额外排查点
- 检查模块
__manifest__.py是否正确声明依赖(如依赖base、studio,若使用Studio生成的字段) - 查看Odoo完整日志,确认是否有前置错误导致字段创建失败
- 可先注释域和
onchange代码,先让字段成功创建,再逐步添加动态逻辑
内容的提问来源于stack exchange,提问作者Fed C
相关产品推荐
相关产品推荐

