Odoo技术问题:打开表单视图并在关闭时获取可用返回值
Odoo表单视图关闭时获取返回值的实现方案
可行性说明
这个需求完全可行,Odoo的前端OWL框架与后端RPC机制支持视图间的数据传递,通过自定义动作、前端事件监听或弹窗组件即可实现。
方案一:弹窗式表单视图(推荐)
适合临时创建/编辑数据并返回结果的场景,通过弹窗触发表单,关闭时传递数据。
1. 后端定义弹窗动作
在触发弹窗的模型中添加方法,返回弹窗配置:
from odoo import models, fields, api class YourSourceModel(models.Model): _name = 'your.source.model' def action_open_popup_form(self): return { 'name': '填写目标数据', 'type': 'ir.actions.act_window', 'res_model': 'target.data.model', # 表单对应的目标模型 'view_mode': 'form', 'target': 'new', # 弹窗模式 'context': { 'default_related_field': self.source_field, # 传递默认值到弹窗 } }
2. 前端监听弹窗关闭事件
在源模型的前端JS文件中,监听弹窗关闭时的事件并处理返回数据:
/** @odoo-module */ import { registry } from "@web/core/registry"; import { formView } from "@web/views/form/form_view"; registry.category("views").add("your_source_model_form", { ...formView, setup() { super.setup(); // 监听弹窗数据返回事件 this.env.bus.on('popup_data_return', this, this.handleReturnData); }, handleReturnData(data) { // 处理返回的数据,示例:更新当前视图字段 this.model.root.data.returned_field = data.target_field; // 保存当前记录 this.model.root.save(); }, });
3. 弹窗表单触发返回事件
在目标模型中重写保存方法,通过bus发送返回数据:
class TargetDataModel(models.Model): _name = 'target.data.model' def write(self, vals): res = super().write(vals) // 向前端发送数据返回事件 self.env['bus.bus']._sendone(self.env.user.partner_id, 'popup_data_return', { 'id': self.id, 'target_field': self.your_field, }) return res def create(self, vals): record = super().create(vals) self.env['bus.bus']._sendone(self.env.user.partner_id, 'popup_data_return', { 'id': record.id, 'target_field': record.your_field, }) return record
方案二:普通表单视图的返回逻辑
如果使用非弹窗的普通表单视图,可通过修改关闭按钮行为实现数据返回:
1. 自定义表单关闭按钮
在目标模型的XML视图中重写关闭按钮:
<record id="target_data_form_view_custom" model="ir.ui.view"> <field name="name">target.data.form.view.custom</field> <field name="model">target.data.model</field> <field name="inherit_id" ref="target_data_form_view"/> <field name="arch" type="xml"> <xpath expr="//button[@name='action_close']" position="replace"> <button name="action_close_and_return" string="关闭并返回" type="object" class="btn-secondary"/> </xpath> </field> </record>
2. 后端定义返回方法
在目标模型中添加关闭回调方法,传递返回数据:
class TargetDataModel(models.Model): _name = 'target.data.model' def action_close_and_return(self): // 组装返回数据 return_data = { 'id': self.id, 'field1': self.field1, 'field2': self.field2, } // 触发客户端动作传递数据 return { 'type': 'ir.actions.client', 'tag': 'pass_return_data', 'params': return_data, }
3. 前端处理客户端动作
在源模型的JS中注册客户端动作,接收并处理返回数据:
registry.category("ir.actions.client").add("pass_return_data", (env, action) => { const returnData = action.params; // 更新源视图数据 const currentView = env.services.view.currentView; if (currentView.modelName === 'your.source.model') { currentView.model.root.data.field1_from_return = returnData.field1; currentView.model.root.save(); } // 关闭当前表单视图 env.services.action.doAction({type: 'ir.actions.act_window_close'}); });
注意事项
- 使用
bus.bus传递事件时,必须指定当前用户作为接收方,避免数据泄露。 - 弹窗模式下
target='new'会自动关闭弹窗,无需额外处理关闭逻辑。 - 复杂场景可通过上下文
context传递临时数据,或使用模型临时字段存储中间值。
内容的提问来源于stack exchange,提问作者GNETO DOMINIQUE
相关产品推荐
相关产品推荐

