Odoo 17选择字段仅显示子集且兼容历史数据的问题
解决Odoo v17自定义选择字段Widget兼容历史数据的TypeError问题
问题分析
你遇到的TypeError是因为自定义Widget渲染历史发票时,当前字段值('e'/'f'/'g')不在你定义的可选列表中,导致Widget无法找到对应的选项定义,从而抛出错误。
解决方案
核心思路:自定义Widget渲染时自动将当前记录的实际值(即使不在显示列表中)临时加入可选选项,既保证新发票只显示指定选项,又兼容历史数据正常显示。
1. 编写自定义Widget的JS代码
在你的模块下创建static/src/js/custom_serie_select.js文件,继承Odoo原生FieldSelect并修改选项获取逻辑:
odoo.define('your_module.custom_serie_select', function (require) { "use strict"; const FieldSelect = require('web.basic_fields').FieldSelect; const registry = require('web.field_registry'); const CustomSerieSelect = FieldSelect.extend({ _getOptions: function () { // 定义新发票允许显示的选项 const allowedOptions = [ {value: 'a', label: this.env._t('Serie A')}, {value: 'i', label: this.env._t('Serie I')}, {value: 'cp', label: this.env._t('Serie CP')}, ]; const currentValue = this.value; // 检查当前值是否在允许列表中,不在则从原字段定义取标签并临时添加 if (currentValue && !allowedOptions.some(opt => opt.value === currentValue)) { const originalSelection = this.field.selection || []; const matchedLabel = originalSelection.find(item => item[0] === currentValue)?.[1] || currentValue; allowedOptions.push({value: currentValue, label: matchedLabel}); } return allowedOptions; }, }); registry.add('custom_serie_select', CustomSerieSelect); return CustomSerieSelect; });
2. 配置模块资产加载
在模块的__manifest__.py中添加JS文件加载配置,确保Widget被正确注册:
{ # ...其他配置项 'assets': { 'web.assets_backend': [ 'your_module/static/src/js/custom_serie_select.js', ], }, }
3. 保持字段定义不变
继续保留原serie字段的完整选项定义,不要删除历史选项:
from odoo import models, fields class AccountMove(models.Model): _inherit = 'account.move' serie = fields.Selection([ ('a', 'Serie A'), ('i', 'Serie I'), ('cp', 'Serie CP'), ('e', 'Serie E'), ('f', 'Serie F'), ('g', 'Serie G'), ], string='Serie', widget='custom_serie_select')
效果说明
- 新创建发票:下拉框仅显示
a/i/cp三个选项,符合需求。 - 历史发票:打开值为
e/f/g的记录时,Widget自动将该值加入临时选项列表,用原字段定义的标签显示,避免TypeError错误。
内容的提问来源于stack exchange,提问作者Ernesto Ruiz
相关产品推荐
相关产品推荐

