刚接触Odoo的时候,我几乎被“设置”和“访问权限”这两个词绕晕。第一次给同事开账号,打开用户表单,一眼看到两个标签页,里面全是密密麻麻的勾选框。我当时的反应是:这俩不是一回事吗?不都是给用户开权限吗?后来在真实项目里配权限、查问题,被客户问过无数次“为什么勾了这里那里还是没权限”,才慢慢把这两个东西的边界彻底摸清楚。这篇就把它们的本质区别和实操经验一次性讲透。
先说明一下,这篇主要讨论的是Odoo后台“用户”表单里的“设置”标签页和“访问权限”标签页,同时也涉及群组管理界面里另一层“访问权限”菜单(ir.model.access 的管理页面)。很多人的困惑其实是因为这几个入口名字接近、界面上的内容也长得像,但背后的设计逻辑差别非常大。
1. 三个入口的定位:先分清界面上的同名概念
1.1 用户表单里的“设置”与“访问权限”标签页
在Odoo后台,进入“设置 -> 用户与公司 -> 用户”,打开任意一个用户,你会看到页面上有多个标签页,其中“设置”和“访问权限”永远是新手最先点开的两个。
“访问权限”标签页里,内容按应用模块分类陈列。比如“联系人”下面有“联系人/用户:全功能”“联系人/经理:全功能”,“销售”下面有“销售/用户:仅自己的文档”“销售/经理:所有文档”,“库存”下面有“库存/用户”“库存/经理”。这里的每一项本质上都是一个“群组”(res.groups),勾选它,就代表把该用户加入这个群组,从而获得该群组定义的业务角色。
“设置”标签页里陈列的则是另一类群组,比如“技术功能”(开发者模式)、“多公司”、“多语言”,还有某些模块暴露出来的功能开关,比如“允许导出”“主页仪表盘”之类。不同版本、不同模块安装情况下的内容差异很大,但共同点是:这些群组大多不直接对某一个业务模型“拥有读改写权限”,而是用来启用系统层面的某项能力或界面元素。
1.2 后台菜单里的“群组”和“访问权限”入口
除了用户表单,Odoo在“设置”菜单下还有独立的“群组”入口,以及藏在“技术 -> 安全 -> 访问权限”里的“访问权限”菜单。这两个入口同样是权限管理的重要位置。
“群组”菜单管理所有群组本身:可以查看群组成员、群组继承关系、菜单访问、记录规则、字段权限等。一个群组在Odoo里不只是一个“名字”,它是一整套权限包。
“技术 -> 安全 -> 访问权限”菜单才是真正的模型级 ACL(Access Control List)管理页面,这里维护的是 ir.model.access 记录。每一行表示:某个群组对某个模型是否拥有创建、读取、修改、删除权限。很多实施人员容易在这个地方犯迷糊——用户表单里的“访问权限”标签页,只是在把用户加入角色群组,并不直接展示模型级 ACL 明细;而“技术 -> 安全 -> 访问权限”菜单展示的才是模型级别的具体规则。
1.3 三个入口的功能对照
| 入口 | 位置 | 管理对象 | 典型用途 |
|---|---|---|---|
| 用户表单“设置”标签页 | 设置 -> 用户 -> 用户 -> 设置 | 功能开关类群组(技术功能、多公司等) | 启用系统能力 |
| 用户表单“访问权限”标签页 | 设置 -> 用户 -> 用户 -> 访问权限 | 业务角色类群组(销售/用户、库存/经理等) | 授予业务角色 |
| 技术 -> 安全 -> 访问权限菜单 | 设置 -> 技术 -> 安全 -> 访问权限 | ir.model.access 模型级 ACL 明细 | 精确控制每个模型的增删改查 |
这样一看,界面上的“设置”和“访问权限”只是同一个用户表单里,按群组的“类别”做了两个陈列窗口而已。真正的差异不在界面,而在这些群组被赋予的职责。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 底层逻辑:所有群组都存于一张表,差异来自“用途”
2.1 用户的所有群组,最终都写进同一个字段
无论你是通过“设置”标签页勾选,还是通过“访问权限”标签页勾选,最终都发生在同一个字段上:res.users.groups_id。在数据库层面,用户与群组的关系表是 res_users_groups_rel,里面存的就是 uid 和 gid 的对应关系。
这一点极其重要。很多初次接触Odoo权限的人以为“设置”和“访问权限”是两套不同的权限系统,实际上它们是同一套系统的两个入口。Odoo 的用户表单视图,只是根据群组的“分类”(category_id)和某些标记,把 groups_id 字段的可选群组拆分到了不同标签页里展示,方便管理员按使用场景去勾选。
2.2 category_id 决定了群组出现在哪个标签页
每个群组都挂在一个“模块分类”(module category)下。比如“销售/用户”这个群组的 category_id 指向“销售”分类,“库存/经理”指向“库存”分类。这些分类通常是业务应用模块自带的安全分类,在界面上就会显示在“访问权限”标签页。
而“技术功能”“多公司”这类群组,一般挂在特殊的分类下,或者被标记为 base.module_category_hidden 之类的类型,因此被过滤到“设置”标签页展示。
我在自定义模块里新建群组时,常常会被问到“怎么让这个群组出现在访问权限页还是设置页”。答案就在这里:改它的 category_id 指向。指向业务应用分类,就出现在“访问权限”页;指向功能/隐藏分类,就出现在“设置”页。这不是什么神秘逻辑,就是分类过滤。
2.3 功能组与安全组的语义差异
虽然底层存储方式一样,但行业里习惯把这两类群组称为功能组(Feature Group)和安全组(Access Group)。它们的职责完全不同:
安全组描述的是“角色”。比如“销售/经理”,它代表一个角色的数据访问范围(所有销售订单、可配置价格)和模型操作权限(可创建、可修改、可删除)。在群组定义里,这类组通常被多个业务模块的 ir.model.access 规则引用,也会通过记录规则(ir.rule)限制数据可见范围。
功能组描述的是“系统能力”。比如“技术功能”,它本身不授予任何业务模型的权限,但会决定是否显示“技术”菜单,让该用户进入开发者相关界面。再比如“多公司”,它启用的是多公司环境下“同时管理多个公司”的界面和上下文切换能力。
用一个生活化的类比:安全组决定了“你能不能进某个房间,以及进了房间能碰哪些东西”;功能组决定了“这栋楼是否安装了电梯,以及你能否看到电梯按钮”。电梯按钮就算亮着,你也不代表能进入每一间上锁的房间。
2.4 权限效果的叠加关系
Odoo 的权限判定是“并集”逻辑:用户拥有多个群组时,只要任意一个群组授予了某个模型的写权限,用户就拥有这个模型的写权限;记录规则方面则根据规则类型不同,可能取并集或交集。这意味着“设置”标签页里的功能组和“访问权限”标签页里的安全组,在实际运行时会叠加生效。
我遇到过客户擅自勾选了“技术功能”后,原本只负责业务录入的员工突然看到了“设置 -> 技术”菜单,还能进入一些开发调试页面。虽然他没有额外数据权限,但菜单多了,误操作的风险也上来了。这就是“功能组影响权限边界”的典型案例——它不直接给模型打洞,但它把本该藏起来的工具暴露出来了。
3. 五个高频场景,帮你把两个标签页的边界试出来
3.1 场景一:勾了“技术功能”却看不到技术菜单
“技术功能”群组在“设置”标签页里,英文是 Technical Features,系统名称 base.group_no_one。这个群组的名字本身就很关键—— no_one,意思是“一般人不该有”。勾了它之后,你确实会看到“设置”菜单下多出“技术”子菜单,但前提是你当前用户本身还必须是内部用户(base.group_user),并且需要退出重新登录。
如果勾了之后刷新页面仍然看不到“技术”菜单,先别急着怀疑权限系统。可以按这个顺序排查:是否勾选后没有重新登录;当前账号是否被设为“外部用户”而不是“内部用户”;浏览器的会话缓存是否太久。多数情况是这三个原因之一。外部用户即使勾了“技术功能”,也不会获得后台完整界面。
3.2 场景二:给经理角色,自动多出用户角色
在“访问权限”标签页里,勾选“销售/经理”之后,你可能会发现“销售/用户”也自动被勾上了,这不是系统抽风,而是群组的“隐含继承”机制在起作用。
在群组设计里,经理组通常通过 implied_ids 字段隐式包含了用户组。比如“销售/经理”的定义里写明了“继承销售/用户”,所以给经理权限时,底层用户权限会连带授予。这个设计的初衷是避免重复配置:经理能做的,肯定包含用户能做的。但这也带来一个常见误解,很多新人在查看用户群组时,看到“怎么多了几个我根本没勾的组”,以为系统出了毛病,其实这是正常行为。
如果你在设计自定义群组时,希望某个上层角色自动拥有下层角色权限,就在群组的“继承的权限”里添加对应群组。这个字段在界面和 XML 定义里都能设置。
3.3 场景三:加了“库存/用户”仍看不到某个库存菜单
“访问权限”标签页里已经勾了“库存/用户”,但用户登录后看不到库存应用的部分菜单。查了半天,最后发现原因是:该用户在“设置”标签页没有被勾选“内部用户”,或者更精确地说,用户类型被设成了“外部用户”。
Odoo 的菜单可见性由 ir.ui.menu 的 groups_id 控制,但绝大多数后台菜单都要求用户至少具备 base.group_user(内部用户)这个基础群组。如果用户连内部用户都不是,即使你给他加了库存角色,他也只会看到非常有限的界面。所以我在配置账号时有一个习惯:先确认“设置”标签页里的“内部用户”是勾选状态,再去看“访问权限”标签页里的业务角色。这个顺序错了,后面很容易全乱。
另一个隐藏原因可能是菜单本身关联了“技术功能”群组,只有技术人员可见。所以排查菜单不见的问题时,既要看“访问权限”里的角色,也要看“设置”里的功能组。
3.4 场景四:客户要“只读权限”到底在哪配
这是项目实施中问得最多的需求:“给某某人只读权限,让他能看到销售订单但不能改。”很多人第一反应是去用户表单的“访问权限”标签页里找“只读”开关,可惜这里没有直接的“只读”勾选框。
“只读”通常需要两层配合。第一层是模型级 ACL,在“技术 -> 安全 -> 访问权限”里,给该用户使用的群组设置某个模型 perm_write 为 0。第二层是字段级权限和记录规则,限制他能看哪些记录、能改哪些字段。如果只是想让某个人不能修改已有销售订单,但能创建新订单,那还需要在记录规则里控制。
实际操作中,我通常建议客户不要直接改标准群组,而是新建一个“只读客户”群组,把需要只读访问的模型 ACL 设置成只读,再把用户加入这个群组。这种做法在用户表单的“访问权限”标签页里就能看到这个新群组,不会被“设置”标签页里的功能开关干扰。
3.5 场景五:在设置里勾了“多公司”,访问权限没变化
“多公司”群组(base.group_multi_company)是一个典型的功能组。勾选它之后,用户的界面右上角会出现公司切换下拉框,也可以在多公司环境下访问多个公司的数据。但如果你跑到“访问权限”标签页去看,不会发现任何新增的角色勾选。
这些功能开关和历史数据权限是两回事。多公司只是给你一把“切换公司视角”的钥匙,至于你能不能看某家公司的数据,取决于记录规则里公司字段的过滤条件。很多实施项目里,因为把这两个概念混在一起,导致用户能看到公司切换按钮,但切换过去后页面空白,或者提示没有访问权限。
4. 权限给了却不生效?按这个顺序排查
4.1 先确认用户是否重新登录
Odoo 的权限在用户登录会话生成时会被缓存到会话数据中。管理员在后台给某个用户加了群组,该用户如果一直没有退出重新登录,新权限不会立即生效。尤其在实际项目中,用户常常一天到晚开着浏览器不关,权限加了半天,那边还反馈“不行”,一查是没刷新。
这个排查最简单,但也最容易被忽略。我的处理习惯是:改完权限后,直接告诉对方退出账号重新登录,不要只按 F5 刷新,因为部分权限数据在 RPC 层也有缓存,刷新页面不一定能清干净。实在不行,可以换一个隐身窗口验证。
4.2 检查用户类型和基础群组
我实际排查权限问题时,第一个动作是打开用户表单的“设置”标签页,确认用户类型是“内部用户”。这个字段虽然不起眼,但它决定了后续所有业务角色是否真的能落到界面上。
如果用户类型是“外部用户”,即使“访问权限”标签页里勾了一堆业务角色,他能看到的也可能只是门户页面,而不是完整的后台界面。外部用户一般用于客户门户、供应商门户等场景,和后台员工的权限模型几乎是两套逻辑。所以给员工开账号时,优先确认“内部用户”。
4.3 确认模块是否更新,ACL 是否重新生成
还有一种隐蔽情况:你在一开始给用户勾选了某个群组,但后来系统里安装了新模块,或者修改了旧模块的权限 XML,如果没有执行“升级模块”操作,新的 ir.model.access 规则可能根本不会写入数据库。这时用户表单里看起来群组是勾着的,但实际权限不完整。
尤其是在开发阶段,修改了 security/ir.model.access.csv 文件之后,必须到“应用”列表里点击对应模块的升级按钮。我见过不少开发新手在后台手动勾了一个组,但代码里对应权限的 CSV 没更新或者升级失败,导致权限规则缺失,数据都读不出来。升级后重新登录再验证,通常问题就解决了。
4.4 用开发者模式直接查看实际生效的群组
如果以上都查过还是不对,可以开启开发者模式,打开“设置 -> 技术 -> 用户”,找到目标用户,查看 groups_id 字段实际包含了哪些群组。这里的列表是数据库直接查询结果,不受表单标签页过滤影响。有时你会发现某个群组在表单里看着勾上了,实际上保存时上下文不对,或者被某种安全规则拦截了。
我在这里查出来的问题五花八门:有的用户被某个自动化动作脚本意外删除了群组,有的被群组继承关系带偏了方向。开发者模式下的原始数据是排障时的最终依据。
4.5 检查记录规则和字段权限
如果用户能看到菜单、能打开页面,但某些记录不显示或者某些字段不能编辑,那问题就出在记录规则(ir.rule)和字段权限(ir.model.fields)上。记录规则在“技术 -> 安全 -> 记录规则”菜单里查看,字段权限在“技术 -> 模型 -> 字段”里查看。
我有时会直接通过 RPC 或后台 Python 控制台测试:以目标用户身份读取某个模型,看返回的记录数量和报错信息,再逐步缩小范围。这种排障方式虽然技术门槛高一些,但定位问题非常快。对于管理员而言,至少要学会在“记录规则”菜单里按群组筛选,看目标用户所在群组的规则是否限制了公司条件、负责人条件等。
5. 群组设计落地的实际建议:把“功能”和“角色”拆开
5.1 命名规范要能一眼区分功能组和安全组
我在自定义模块里维护群组时,有一个坚持了几年的习惯:安全组一定按“应用/角色”的格式命名,比如“项目验收/用户”“项目验收/经理”;功能组一定以“允许/启用”开头,比如“允许项目成本查看”“启用自定义仪表盘”。
这样做的好处是,后续在“访问权限”标签页和“设置”标签页里看群组名称时,能立刻判断它出现在哪个位置、作用是什么。如果命名随意,时间一长连自己都会搞混。群里也经常有同行问:“我在设置页建了一个群组,为什么权限不对?”十有八九是建组时没想清楚它是功能开关还是角色权限。
5.2 用 implied_ids 做角色继承,别重复勾选
经理角色包含用户角色,这是Odoo最常见的角色继承关系。在定义群组时,用 implied_ids 把下层角色挂到上层角色上。这样在“访问权限”标签页里,只勾选“经理”,系统会自动把底层“用户”权限一起带出来。
需要提醒的是,反向操作时要小心。如果把“用户”组和“经理”组做成完全平级、互不含盖的关系(即没有 implied_ids),那么给用户授权时必须手动勾两个组,漏一个就可能出现“能建单但不能看单”之类的怪问题。我刚做Odoo那会儿就犯过这种错,当时花了一下午才排查出来,原因就是两个组在 XML 里都干净得没有继承关系。
5.3 上线前的权限配置自查清单
每个项目上线前,我会按这个清单检查一遍,能省下大量售后问题:
- 每个员工账号是否为“内部用户”。
- 是否已在“访问权限”标签页勾选对应业务角色。
- 是否因角色继承而自动带出了基础角色。
- 是否在“设置”标签页误勾了“技术功能”。
- 是否所有自定义模块都已完成升级,ACL 规则已生成。
- 是否用只读测试账号实际走一遍关键业务流程。
- 是否在记录规则中检查了公司、负责人、项目等过滤条件。
这套流程执行下来,权限相关的工单数量明显下降。最后再分享一个查权限的小技巧:别在“用户”表单里反复看勾选框,直接打开“设置 -> 用户 -> 群组”,从群组角度去看它都包含哪些用户。管理者只要培养起“先想群组,再想用户”的思维,设置和访问权限的区别就不再是障碍了。
