You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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="[
                   '|',
                   '&amp;',
                   (parent.picking_type_code, '=', 'outgoing'),
                   (parent.customer, '!=', False),
                   '&amp;',
                   ('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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:45:05