如何针对不同门户用户限制Odoo website.menu访问?已写代码未生效
Odoo门户用户菜单可见性权限排查与替代方案
一、现有继承方案的常见问题排查
- 计算方法覆写逻辑遗漏:检查
_compute_visible方法是否完整保留原逻辑(如菜单发布状态、网站匹配等),同时正确关联用户类型判断。比如未调用super()导致基础可见性判断失效,或者用户组判断代码错误(如未正确获取self.env.user的分组信息)。 - 权限字段配置失效:确认扩展的权限字段(如
visible_for_employee)已正确添加到数据库,且在菜单表单视图中能正常编辑保存。可直接查询数据库表website_menu,查看对应字段值是否已存储。 - 缓存依赖未设置:计算字段需添加正确的依赖触发重计算,比如在
_compute_visible装饰器中加入@api.depends('visible_for_employee', 'visible_for_parent', 'env.user.groups_id'),避免权限变更后缓存未更新。 - 前端渲染逻辑冲突:Odoo门户菜单渲染默认调用
menu.is_visible()方法而非直接读取_visible字段,若仅覆写计算字段而未处理该方法,会导致前端仍按原逻辑显示菜单。
二、替代实现方案
方案1:利用内置组权限字段(无需继承模型)
Odoo自带groups_id字段可直接控制菜单可见性,步骤如下:
- 创建门户用户专属组:如
group_portal_employee(员工)、group_portal_parent(家长),并设置为base.group_portal的子组。 - 在菜单表单视图中启用
groups_id字段,给对应菜单分配允许查看的用户组。Odoo会自动根据当前用户所属组判断菜单是否显示,无需自定义代码。
方案2:模板层直接控制可见性
在门户菜单渲染模板中添加条件判断,适合固定场景的权限控制:
<!-- 示例:自定义门户菜单模板片段 --> <t t-foreach="menu.children" t-as="submenu"> <t t-if="user.has_group('your_module.group_portal_employee') and submenu.name == '员工专属菜单'"> <li><a t-attf-href="#{submenu.url}"><t t-esc="submenu.name"/></a></li> </t> <t t-if="user.has_group('your_module.group_portal_parent') and submenu.name == '家长专属菜单'"> <li><a t-attf-href="#{submenu.url}"><t t-esc="submenu.name"/></a></li> </t> </t>
方案3:覆写is_visible()方法(推荐)
直接覆写菜单的可见性判断方法,适配前端渲染逻辑:
from odoo import models, fields, api class WebsiteMenu(models.Model): _inherit = 'website.menu' visible_for_employee = fields.Boolean(string="员工可见") visible_for_parent = fields.Boolean(string="家长可见") def is_visible(self): # 先执行原逻辑判断基础可见性 base_visible = super().is_visible() if not base_visible: return False # 仅对门户用户做权限判断 if self.env.user.has_group('base.group_portal'): emp_group = self.env.user.has_group('your_module.group_portal_employee') parent_group = self.env.user.has_group('your_module.group_portal_parent') # 若菜单未设置权限,默认隐藏;或根据需求调整逻辑 if (self.visible_for_employee and emp_group) or (self.visible_for_parent and parent_group): return True return False # 内部用户按原逻辑处理 return base_visible
内容的提问来源于stack exchange,提问作者Raihan
相关产品推荐
相关产品推荐

