【ODOO技术问题】如何在XML模板中调用Python模型的方法/属性?
Odoo前端模板调用Python模型字段的解决方案
直接在QWeb模板中使用t-esc="notification_count"无法生效,核心原因是:Odoo的前端QWeb模板上下文默认不会自动包含Python模型的字段值,必须通过后端把数据注入模板上下文,或者前端主动调用后端API获取数据。
方法1:通过控制器注入数据到模板上下文
扩展Menu对应的控制器,在渲染模板时把通知计数传递到上下文:
步骤1:编写控制器代码
from odoo import http from odoo.http import request class ExtendedMenuController(http.Controller): @http.route() def web_client(self, **kw): # 调用父类方法获取原始响应 response = super().web_client(**kw) # 计算当前用户的通知总数 notification_count = request.env['notification.notification.public'].search_count([]) # 将计数注入QWeb模板的上下文变量 response.qcontext['notification_count'] = notification_count return response
步骤2:修改XML模板
直接使用注入的上下文变量即可:
<?xml version="1.0" encoding="UTF-8"?> <templates xml:space="preserve"> <t t-extend="Menu"> <t t-jquery=".o_menu_sections" t-operation="after"> <a class="o_notification_badge" style="cursor: pointer" autofocus="autofocus" aria-label="Notification Badge" accesskey="h"> <i role="img" aria-label="Notifications" class="fa fa-bell"/> <t> <span class="o_NotificationBadge_counter badge badge-pill"> <t t-esc="notification_count"/> </span> </t> </a> </t> </t> </templates>
方法2:前端JS异步调用后端API
如果不想修改控制器,也可以用前端JS通过RPC调用后端方法获取计数,再更新DOM:
步骤1:给Python模型添加可调用方法
class NotificationNotificationPublic(models.Model): _name = 'notification.notification.public' name = fields.Char(string='Title') notification_count = fields.Integer(compute="_compute_notification_count") def _compute_notification_count(self): for record in self: record.notification_count = self.env['notification.notification.public'].search_count([]) # 新增供前端调用的公开方法 def get_notification_count(self): return self.search_count([])
步骤2:修改XML模板并添加JS脚本
<?xml version="1.0" encoding="UTF-8"?> <templates xml:space="preserve"> <t t-extend="Menu"> <t t-jquery=".o_menu_sections" t-operation="after"> <a class="o_notification_badge" style="cursor: pointer" autofocus="autofocus" aria-label="Notification Badge" accesskey="h"> <i role="img" aria-label="Notifications" class="fa fa-bell"/> <t> <span class="o_NotificationBadge_counter badge badge-pill" id="notification-counter">0</span> </t> </a> </t> </t> <!-- 追加JS脚本到页面资源 --> <t t-extend="Assets"> <t t-jquery="head" t-operation="append"> <script type="text/javascript"> odoo.define('notification.badge_counter', function(require) { 'use strict'; var rpc = require('web.rpc'); var core = require('web.core'); core.bus.on('web_client_ready', null, function() { // 调用后端方法获取计数 rpc.query({ model: 'notification.notification.public', method: 'get_notification_count', args: [] }).then(function(count) { $('#notification-counter').text(count); }); }); }); </script> </t> </t> </templates>
注意事项
- 确保当前用户拥有
notification.notification.public模型的读权限,可以在模块的安全配置文件中添加:
<record id="access_notification_public" model="ir.model.access"> <field name="name">Access to Public Notifications</field> <field name="model_id" ref="model_notification_notification_public"/> <field name="group_id" ref="base.group_user"/> <field name="perm_read" eval="True"/> </record>
- 方法1是同步渲染,页面加载时直接显示计数;方法2是异步加载,适合数据可能动态变化的场景。
内容的提问来源于stack exchange,提问作者WilliamVietnam
相关产品推荐
相关产品推荐

