如何使用bus.bus连接Python与JS?求机制及代码实现方案
使用bus.bus实现Python与JS的双向触发(Odoo环境)
一、单个用户触发:Python调用后触发指定客户端函数
Python端代码调整
你的模型函数里,用_sendone给指定用户发消息即可,需明确用户ID、唯一频道和带类型的消息体,确保JS端能精准识别:
from odoo import models class MyModel(models.Model): _name = 'my.model' _description = 'My Model' def my_func(self): # 先执行你的业务逻辑 # 发送触发消息 target_user_id = self.env.user.id # 可替换为目标用户ID # 自定义唯一频道,建议用模型+记录ID,避免频道冲突 channel = f'my.model.trigger.{self.id}' # 消息体带type字段,方便JS区分事件类型 message = { 'type': 'call_test', 'record_id': self.id # 可选:给JS传递额外业务数据 } self.env['bus.bus']._sendone(target_user_id, channel, message)
JS端绑定事件
在组件中利用Odoo全局bus订阅对应频道,收到指定类型消息时调用test(),注意组件销毁时取消订阅,避免内存泄漏:
import { Component } from "@odoo/owl"; import { bus } from "@web/core/bus"; export class MyComponent extends Component { setup() { super.setup(); // 订阅与Python端完全一致的频道(假设组件可获取当前记录ID) this.channel = `my.model.trigger.${this.props.record.id}`; // 绑定消息处理函数 this.subscription = bus.subscribe(this.channel, this.onMessageReceived.bind(this)); } onMessageReceived(message) { // 仅处理我们需要的事件类型 if (message.type === 'call_test') { this.test(); // 可直接使用Python传递的额外数据,如message.record_id } } test() { console.log('works'); } willUnmount() { // 组件卸载时必须取消订阅 this.subscription.unsubscribe(); } }
二、全局广播:向所有活跃用户触发JS函数
要给所有在线用户发消息,用_sendbroadcast替代_sendone,无需指定用户,所有订阅对应频道的客户端都会收到:
Python端广播代码
def broadcast_to_all(self): # 先执行业务逻辑 # 定义全局频道 global_channel = 'my.model.global.broadcast' message = { 'type': 'global_call_test', 'notice': '这是给所有用户的通知' } self.env['bus.bus']._sendbroadcast(global_channel, message)
JS端订阅全局频道
在组件中额外订阅全局频道即可:
setup() { super.setup(); // 订阅全局频道 this.globalChannel = 'my.model.global.broadcast'; this.globalSub = bus.subscribe(this.globalChannel, this.onGlobalMessage.bind(this)); // 保留单个用户的频道订阅(如有需要) this.channel = `my.model.trigger.${this.props.record.id}`; this.subscription = bus.subscribe(this.channel, this.onMessageReceived.bind(this)); } onGlobalMessage(message) { if (message.type === 'global_call_test') { console.log(message.notice); this.test(); // 触发全局函数 } } willUnmount() { this.subscription.unsubscribe(); this.globalSub.unsubscribe(); }
三、bus.bus使用实用建议
- 频道命名规范:采用
模块名.模型名.用途.标识格式(如my_module.my.model.record.123),避免与其他模块频道冲突,便于后期维护。 - 消息结构统一:所有消息必须携带
type字段,JS端通过type区分不同事件,禁止传递无结构的零散数据,防止逻辑混乱。 - 订阅生命周期管理:组件挂载时订阅,卸载时必须取消订阅,避免用户切换页面后仍收到无效消息,引发内存泄漏或逻辑错误。
- 权限控制:发送消息前验证用户权限,比如禁止普通用户触发管理员专属通知,防止敏感数据泄露。
- 幂等性处理:若业务场景需避免重复执行,给消息添加唯一ID,JS端记录已处理的ID,防止重复触发逻辑。
- 调试技巧:Python端用
self.env['bus.bus']._log(message)打印消息日志,JS端直接console.log(message),快速排查问题。
内容的提问来源于stack exchange,提问作者Wald Sin
相关产品推荐
相关产品推荐

