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

如何将RPC响应数据在继承模板中正确展示?

问题:Odoo中RPC获取用户数据后模板无法渲染显示

我尝试通过RPC获取当前用户数据并在列表视图按钮模板中展示,JS代码能在控制台输出预期数据,但模板里的widget.user始终为空。

我的实现代码

JS部分:

var session = require('web.session');
var rpc = require('web.rpc');

var ListController = require('web.ListController');
ListController.include({
  renderButtons: function($node) {
    this._super.apply(this, arguments);
    rpc.query({
      model: 'res.users',
      method: 'search_read',
      args: [
        [['id','=',session.uid]],
        ['id','name','login'],
      ],
    }).then(res => {
      this.user = res[0];
      console.log(this);
      // 曾尝试把_super移到这里,结果出现随机错误
    });
  },
});

XML模板部分:

<?xml version="1.0" encoding="UTF-8"?>
<template xml:space="preserve">
  <t t-extend="ListView.buttons">
    <t t-jquery="button.o_list_button_add" t-operation="replace">
      <button class="btn btn-primary o_list_button_add" type="button">Create</button>
      <span t-esc="widget.user"/>
    </t>
  </t>
</template>

问题原因

  1. RPC请求是异步操作,renderButtons执行完_super就直接渲染模板了,此时this.user还未被赋值,所以模板里拿不到数据。
  2. 不能把_super移到then回调里,因为_super是负责渲染初始按钮DOM的核心逻辑,延迟调用会破坏视图初始化流程,导致各种未知错误。

解决方法

方法1:重新渲染按钮区域(推荐)

在获取到用户数据后,重新调用renderButtons更新DOM,同时要先保存初始的$node:

var session = require('web.session');
var rpc = require('web.rpc');

var ListController = require('web.ListController');
ListController.include({
  renderButtons: function($node) {
    // 保存节点引用,用于后续重新渲染
    this.buttonNode = $node;
    this._super.apply(this, arguments);
    
    // 初始化user避免模板报错
    if (!this.user) {
      rpc.query({
        model: 'res.users',
        method: 'search_read',
        args: [
          [['id','=',session.uid]],
          ['id','name','login'],
        ],
      }).then(res => {
        this.user = res[0];
        // 重新渲染按钮,此时user已经有值
        this.renderButtons(this.buttonNode);
      });
    }
  },
});

模板可以优化为处理未加载状态:

<?xml version="1.0" encoding="UTF-8"?>
<template xml:space="preserve">
  <t t-extend="ListView.buttons">
    <t t-jquery="button.o_list_button_add" t-operation="replace">
      <button class="btn btn-primary o_list_button_add" type="button">Create</button>
      <span t-if="widget.user" t-esc="widget.user.name"/>
      <span t-else>Loading...</span>
    </t>
  </t>
</template>

方法2:直接更新DOM元素(更高效)

如果不想重新渲染整个按钮区域,可以在获取数据后直接找到对应元素修改内容:

var session = require('web.session');
var rpc = require('web.rpc');

var ListController = require('web.ListController');
ListController.include({
  renderButtons: function($node) {
    this._super.apply(this, arguments);
    
    rpc.query({
      model: 'res.users',
      method: 'search_read',
      args: [
        [['id','=',session.uid]],
        ['id','name','login'],
      ],
    }).then(res => {
      this.user = res[0];
      // 直接找到模板里的span元素赋值
      this.$('.o_list_button_add').next('span').text(this.user.name);
    });
  },
});

这种方式不需要重新渲染,性能更好,适合只更新局部内容的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:14:53