Odoo16中JavaScript调用RPC读取记录失败问题排查
Odoo网站模板中JS RPC调用失效的排查及替代方案
先排查RPC调用的核心问题
你能拿到选中项ID但RPC不生效,大概率是格式、权限或环境问题,按下面步骤逐一排查:
1. 核对RPC调用的基础格式
Odoo的JS RPC必须严格遵循规范,下面是标准的read方法调用示例,对照你的代码检查:
// 确保代码放在Odoo环境就绪后执行 odoo.ready(function() { document.getElementById('your-select-id').addEventListener('change', function(e) { const selectedId = parseInt(e.target.value); if (!selectedId) return; odoo.rpc.query({ model: 'project.initiative', // 替换为你的initiative对应模型(必须和后台完全一致) method: 'read', args: [[selectedId], ['name', 'description', 'your_other_fields']] // 第一个元素是ID数组,第二个是要获取的字段列表 }).then(result => { if (result.length) { const initiative = result[0]; // 把详情渲染到页面,比如插入到指定容器 document.getElementById('detail-box').innerHTML = ` <h4>${initiative.name}</h4> <p>${initiative.description || '暂无描述'}</p> `; } }).catch(err => { // 一定要打开浏览器控制台看错误信息,这是排查关键 console.error('RPC调用失败:', err); }); }); });
重点检查:
model名称是否拼写错误(比如后台是project.initiative,你写成了initiative)args的格式:必须是二维数组,ID要放在数组里,字段列表不能漏- 控制台是否有报错(比如
模型不存在、权限不足、字段不存在等)
2. 验证用户权限
网站默认的Public用户组通常没有很多模型的读取权限,这是RPC失败的常见原因:
- 登录Odoo后台,找到你的initiative模型
- 进入「设置」→「权限」,找到对应权限组
- 给
Public组添加「读取」权限,或者创建专门的网站用户组并分配权限
3. 确保代码在Odoo环境就绪后执行
如果你的JS代码加载过早,Odoo的odoo.rpc对象还没初始化,自然调用失败。必须把代码放在odoo.ready()回调里,像上面示例那样。
其他获取记录的替代方式
如果RPC调用实在搞不定,可以试试下面几种方法:
1. 预存详情到下拉选项的Data属性
如果initiative的数量不多,直接在渲染下拉框时把记录详情存在option的data属性里,选中时直接读取,不用发请求:
QWeb模板代码:
<select id="initiative-select"> <t t-foreach="initiative_records" t-as="init"> <option t-att-value="init.id" t-att-data-details='JSON.stringify(init)' > <t t-esc="init.name"/> </option> </t> </select>
JS代码:
odoo.ready(function() { document.getElementById('initiative-select').addEventListener('change', function(e) { const selectedOption = e.target.options[e.target.selectedIndex]; if (!selectedOption.dataset.details) return; const details = JSON.parse(selectedOption.dataset.details); // 直接渲染详情 document.getElementById('detail-box').innerHTML = `<h4>${details.name}</h4><p>${details.description}</p>`; }); });
2. 自定义网站控制器(Python+Fetch)
自己写一个网站路由,返回记录详情,用JS的Fetch API调用:
后台Python代码:
from odoo import http from odoo.http import request class InitiativeDetailController(http.Controller): @http.route('/get-initiative-detail/<int:init_id>', type='json', auth='public') def get_initiative_detail(self, init_id): # 用sudo()确保Public用户能访问,也可以加权限验证逻辑 initiative = request.env['project.initiative'].sudo().browse(init_id) if initiative.exists(): return { 'name': initiative.name, 'description': initiative.description, 'create_date': initiative.create_date.strftime('%Y-%m-%d') } return {}
JS代码:
odoo.ready(function() { document.getElementById('initiative-select').addEventListener('change', function(e) { const initId = parseInt(e.target.value); if (!initId) return; fetch(`/get-initiative-detail/${initId}`) .then(res => res.json()) .then(data => { if (data.name) { document.getElementById('detail-box').innerHTML = `<h4>${data.name}</h4><p>${data.description}</p>`; } }) .catch(err => console.error('获取详情失败:', err)); }); });
3. 使用旧版Web Model(适合Odoo 10-12)
如果是较旧的Odoo版本,可以用web.Model来调用:
odoo.ready(function() { const InitiativeModel = new odoo.web.Model('project.initiative'); document.getElementById('initiative-select').addEventListener('change', function(e) { const initId = parseInt(e.target.value); if (!initId) return; InitiativeModel.call('read', [[initId], ['name', 'description']]) .then(result => { // 处理结果 }) .catch(err => console.error(err)); }); });
内容的提问来源于stack exchange,提问作者nwara97
相关产品推荐
相关产品推荐

