Odoo 17中如何依据其他字段值限制单选按钮选项?
解决方案:动态限制ShipmentPackageLine的package_type选项
原代码无效原因
你之前使用的onchange方法无法生效,核心问题在于:
- 直接修改
package.fields_get()的返回值仅作用于临时对象,不会同步到前端视图的字段定义渲染。 fields_get()是模型级别的字段信息查询方法,针对单个记录的修改无法触发全局视图更新。
正确实现方案
方案1:通过视图属性动态控制选项可见性
直接在XML视图中,针对package_type的单选选项设置可见性规则,基于父模型freight.shipment的字段值判断:
修改freight_shipment_form_view中Package Details页面的package_type字段定义:
<form string="Package"> <group> <label for="package_type"/> <div> <field name="package_type" widget="radio" options="{'horizontal':True}"> <attribute name="attrs"> <attribute name="invisible"> <![CDATA[ (parent.direction == 'export' and parent.transport == 'ocean' and parent.ocean_shipment_type == 'fcl') and (value == 'item') ]]> </attribute> </attribute> </field> </div> </group> <!-- 原有其他内容 --> </form>
该配置会在父记录满足direction='export'、transport='ocean'、ocean_shipment_type='fcl'时,自动隐藏Loose Cargo(item)选项,仅保留Containerized(container)选项。
方案2:通过模型方法动态修改字段选项
如果需要更灵活的逻辑控制,可以在ShipmentPackageLine模型中重写fields_get方法,根据关联的父记录条件动态调整package_type的可选值:
步骤1:修改ShipmentPackageLine模型
class ShipmentPackageLine(models.Model): _name = 'shipment.package.line' _rec_name = 'package' package_type = fields.Selection([('item', 'Loose Cargo'), ('container', 'Containerized')], string="Package Type", default='item') shipment_id = fields.Many2one('freight.shipment', string='Shipment', required=True) @api.model def fields_get(self, allfields=None, attributes=None): res = super().fields_get(allfields=allfields, attributes=attributes) # 遍历当前记录,根据父shipment的条件调整选项 for record in self: shipment = record.shipment_id if shipment.direction == 'export' and shipment.transport == 'ocean' and shipment.ocean_shipment_type == 'fcl': res['package_type']['selection'] = [('container', 'Containerized')] res['package_type']['default'] = 'container' else: res['package_type']['selection'] = [('item', 'Loose Cargo'), ('container', 'Containerized')] return res
步骤2:完善FreightShipment的onchange方法
确保父字段变化时,同步更新子记录的字段值并触发视图刷新:
class FreightShipment(models.Model): _name = 'freight.shipment' # 原有字段定义... @api.onchange('direction', 'transport', 'ocean_shipment_type') def _onchange_shipment_conditions(self): if self.direction == 'export' and self.transport == 'ocean' and self.ocean_shipment_type == 'fcl': # 强制将现有包裹的类型设置为container self.freight_packages.write({'package_type': 'container'}) # 返回空domain触发视图重新渲染,加载动态字段选项 return {'domain': {'freight_packages': []}}
验证效果
完成上述修改后,当满足export+ocean+fcl条件时:
- 新增或编辑包裹时,
package_type仅显示Containerized选项 - 已存在的包裹会自动切换为
Containerized类型
内容的提问来源于stack exchange,提问作者Sheenergizer
相关产品推荐
相关产品推荐

