Odoo16中@api.onchange动态域方法弃用的替代方案求助
解决Odoo16中One2Many子字段动态域替代@api.onchange的方案
问题背景
原代码通过@api.onchange返回域的方式在Odoo16中触发弃用警告,需要实现:根据父模型的customer和picking_type_code字段,动态限制One2Many字段move_ids内product_id的可选范围。
推荐方案:视图层面动态域 + 父字段引用
直接在视图中通过parent变量访问父模型字段,结合Odoo的域逻辑实现动态限制,同时确保父字段变化时自动刷新子字段的域。
1. 修改父模型的Form视图XML
找到父模型对应的form视图,在move_ids的子视图(Tree/Form)中为product_id设置动态域:
<field name="move_ids" widget="one2many_list"> <tree editable="bottom"> <!-- 其他子字段 --> <field name="product_id" domain="[ '|', '&', (parent.picking_type_code, '=', 'outgoing'), (parent.customer, '!=', False), '&', ('picking_id.picking_type_code', '=', 'incoming'), ('picking_id.customer', '=', parent.customer), '|', (parent.picking_type_code, '!=', 'outgoing'), (parent.customer, '=', False) ]"/> <!-- 其他子字段 --> </tree> </field>
域逻辑说明:
- 当父模型的
picking_type_code为outgoing且customer存在时,只允许选择满足picking_id.picking_type_code='incoming'且picking_id.customer等于父模型customer的产品 - 其他情况不限制产品选择
2. 确保父字段变化时刷新子域
在父模型的customer和picking_type_code字段定义中添加on_change=True,触发视图在字段值变化时重新渲染,自动更新子字段的域:
from odoo import fields, models class YourParentModel(models.Model): _name = 'your.parent.model' _description = 'Your Parent Model' customer = fields.Many2one('res.partner', string='Customer', on_change=True) picking_type_code = fields.Selection( [('incoming', 'Incoming'), ('outgoing', 'Outgoing')], string='Picking Type', on_change=True ) move_ids = fields.One2many('stock.move', 'your_parent_id', string='Moves')
替代方案:上下文传递动态域(复杂场景适用)
如果子视图无法直接通过parent访问父字段(比如独立的子Form视图),可以通过上下文传递动态域:
1. 父模型添加计算字段生成域
from odoo import fields, models, api class YourParentModel(models.Model): _name = 'your.parent.model' _description = 'Your Parent Model' customer = fields.Many2one('res.partner', string='Customer') picking_type_code = fields.Selection( [('incoming', 'Incoming'), ('outgoing', 'Outgoing')], string='Picking Type' ) move_ids = fields.One2many('stock.move', 'your_parent_id', string='Moves', context="{'product_domain': product_domain}") product_domain = fields.Char(compute='_compute_product_domain', store=False) @api.depends('customer', 'picking_type_code') def _compute_product_domain(self): for record in self: if record.picking_type_code == 'outgoing' and record.customer: record.product_domain = str([ ('picking_id.picking_type_code', '=', 'incoming'), ('picking_id.customer', '=', record.customer.id) ]) else: record.product_domain = '[]'
2. 子模型视图引用上下文域
在stock.move的视图中,为product_id设置域为上下文传递的值:
<field name="product_id" domain="context.get('product_domain', [])"/>
方案优势
- 符合Odoo16+的架构设计,避免弃用警告
- 视图层面的域逻辑更直观,模型层专注于业务数据处理
- 无需额外的JS代码,原生支持字段变化时的自动刷新
内容的提问来源于stack exchange,提问作者Nisarga Cm
相关产品推荐
相关产品推荐

