Odoo 15:如何让特定组用户隐藏指定菜单项?
Odoo反向权限控制:通过组隐藏指定菜单项的实现思路
你提到的需求是将用户加入特定组后隐藏指定菜单项,但Odoo的权限模型默认是「累加权限」——用户只要拥有任意一个菜单允许的组,就能看到该菜单,常规的groups_id配置无法直接实现反向隐藏。下面是几个可行的实现技巧:
方法一:重写菜单可见性计算方法(最直接)
Odoo菜单的可见性最终由ir.ui.menu的_visible_menu_ids方法决定,我们可以继承这个模型,在方法中加入判断逻辑:如果用户属于目标隐藏组,就从可见菜单列表中移除指定菜单项。
代码示例:
from odoo import models, api class IrUiMenu(models.Model): _inherit = 'ir.ui.menu' @api.model def _visible_menu_ids(self): # 先调用原方法获取默认可见的菜单ID列表 visible_menu_ids = super()._visible_menu_ids() # 判断当前用户是否在「Hide Contacts」组中 hide_contacts_group = self.env.ref('your_module.group_hide_contacts') if hide_contacts_group in self.env.user.groups_id: # 获取要隐藏的菜单项ID contacts_menu_id = self.env.ref('contacts.menu_contacts').id # 如果该菜单在可见列表中,移除它 if contacts_menu_id in visible_menu_ids: visible_menu_ids.remove(contacts_menu_id) return visible_menu_ids
优缺点:
- 优点:逻辑直接,不影响其他权限,用户即使拥有其他能访问联系人的组,只要加入隐藏组就会被屏蔽
- 缺点:需要编写Python代码,对自定义模块有依赖
方法二:利用组关联实现权限互斥
通过创建一个「允许访问联系人」的常规组,再让「Hide Contacts」组与它形成互斥关系——用户加入隐藏组时自动移除允许组的关联,退出时自动恢复。
代码示例(用户组自动同步):
from odoo import models, api class ResUsers(models.Model): _inherit = 'res.users' @api.model def create(self, vals): user = super().create(vals) self._sync_hide_contacts_group(user) return user def write(self, vals): res = super().write(vals) if 'groups_id' in vals: for user in self: self._sync_hide_contacts_group(user) return res def _sync_hide_contacts_group(self, user): hide_group = self.env.ref('your_module.group_hide_contacts') show_group = self.env.ref('your_module.group_show_contacts') # 修改联系人菜单的groups_id为这个show_group if hide_group in user.groups_id: user.write({'groups_id': [(3, show_group.id)]}) else: # 退出隐藏组时自动恢复访问权限 if show_group not in user.groups_id: user.write({'groups_id': [(4, show_group.id)]})
优缺点:
- 优点:利用Odoo原生权限模型,无需修改菜单可见性核心逻辑
- 缺点:需要额外维护一个「允许访问」组,逻辑相对复杂
方法三:通过Action权限间接隐藏菜单
菜单的可见性依赖于其关联的Action权限,我们可以从Action层面控制,让加入隐藏组的用户无法访问对应Action,从而间接隐藏菜单。
代码示例:
from odoo import models, api class IrActionsActWindow(models.Model): _inherit = 'ir.actions.act_window' @api.model def _get_action_domain(self): domain = super()._get_action_domain() if self.env.user.has_group('your_module.group_hide_contacts'): # 排除联系人对应的Action contacts_action_id = self.env.ref('contacts.action_contacts').id domain += [('id', '!=', contacts_action_id)] return domain
优缺点:
- 优点:不仅隐藏菜单,还能限制用户通过其他入口(如快捷按钮)访问该功能
- 缺点:会过度限制,可能影响其他依赖该Action的业务场景
内容的提问来源于stack exchange,提问作者forvas
相关产品推荐
相关产品推荐

