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

Odoo 13:如何在on_change方法中调用向导并实现字段值回传?

解决Odoo字段变化时弹出向导并传递数据的问题

你的思路方向是对的,但Odoo的@api.onchange方法在返回ir.actions.act_window时,前端的处理逻辑有局限(尤其是Odoo 13+版本),直接返回窗口动作通常不会触发弹窗。下面是更可靠的实现方案,完美匹配你的核心需求:

核心思路

通过onchange触发一个带操作按钮的警告提示,用户点击按钮后打开向导;向导接收原记录的ID,输入数据后再回写到原记录中。这种方式是Odoo官方推荐的交互模式,避免了前端的限制。

具体实现步骤

1. 修改原模型的onchange方法

在你的业务模型中,修改on_change方法,返回包含向导触发按钮的警告:

import json
from odoo import models, fields, api

class YourModel(models.Model):
    _name = 'your.model.name'  # 替换为你的模型名
    _description = 'Your Model'

    my_field = fields.Char(string="触发字段")
    target_field = fields.Char(string="接收数据的字段")  # 替换为你要更新的字段

    @api.onchange('my_field')
    def on_change(self):
        if self.my_field:  # 仅当字段有值变化时触发
            # 获取预定义的向导动作
            wizard_action = self.env.ref('my_module.action_open_my_wizard').read()[0]
            # 传递当前记录ID到向导的context中
            wizard_action['context'] = {'default_active_id': self.id}
            # 将动作序列化为前端可识别的字符串
            action_str = json.dumps(wizard_action)
            
            return {
                'warning': {
                    'title': "请补充信息",
                    'message': "需要您输入相关数据,请点击下方按钮打开向导:",
                    'buttons': [
                        {
                            'text': '打开数据输入向导',
                            'type': 'action',
                            'action': action_str,
                        }
                    ]
                }
            }

2. 创建向导模型

新增一个瞬态模型(TransientModel)作为弹窗载体,负责接收用户输入并更新原记录:

from odoo import models, fields, api

class MyWizard(models.TransientModel):
    _name = 'my.wizard'
    _description = '数据输入向导'

    active_id = fields.Many2one('your.model.name', string="关联记录", readonly=True)
    my_field2 = fields.Char(string="需要输入的数据", required=True)

    def save_and_close(self):
        """保存数据到原记录并关闭向导"""
        if self.active_id:
            # 将输入的值写入原记录的目标字段
            self.active_id.write({'target_field': self.my_field2})
        # 返回关闭窗口的动作
        return {'type': 'ir.actions.act_window_close'}

3. 配置向导的视图和动作

在模块的XML文件中定义向导的表单视图和打开动作:

<odoo>
    <!-- 向导表单视图 -->
    <record id="view_my_wizard_form" model="ir.ui.view">
        <field name="name">my.wizard.form.view</field>
        <field name="model">my.wizard</field>
        <field name="arch" type="xml">
            <form string="输入数据">
                <group>
                    <!-- 隐藏关联字段,仅用于传递记录ID -->
                    <field name="active_id" invisible="1"/>
                    <field name="my_field2" placeholder="请输入数据..."/>
                </group>
                <footer>
                    <button name="save_and_close" type="object" string="保存" class="btn-primary"/>
                    <button string="取消" class="btn-secondary" special="cancel"/>
                </footer>
            </form>
        </field>
    </record>

    <!-- 打开向导的动作 -->
    <record id="action_open_my_wizard" model="ir.actions.act_window">
        <field name="name">打开数据输入向导</field>
        <field name="res_model">my.wizard</field>
        <field name="view_mode">form</field>
        <field name="target">new</field>  <!-- 弹窗模式 -->
    </record>
</odoo>

4. 模块配置

确保在__manifest__.py中添加了向导的Python文件和XML视图文件:

{
    # ... 其他配置项
    'data': [
        # ... 其他视图
        'views/my_wizard_view.xml',
    ],
    'depends': ['base'],
}

关键说明

  • 为什么不用直接返回动作?Odoo的onchange事件主要设计用于字段更新和即时提示,前端不会处理返回的窗口动作;而警告框中的按钮是官方支持的交互方式,兼容性更好。
  • 如何传递原记录ID?通过context的default_active_id参数,向导初始化时会自动填充关联字段,后续就能直接操作原记录。
  • 瞬态模型的优势:TransientModel的数据会定期清理,适合这种一次性的临时交互场景。

内容的提问来源于stack exchange,提问作者Raihan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:08:13