增加odoo权限
人生最幸运的两个时刻,一个是出生的时刻,一个就是找到人生目标的时刻,如果还没找到人生目标,那就每天设定一个目标,然后完成它。今天的目标就是搞明白odoo的权限显示。
先看看,权限管理页面:
可以看到odoo权限页面有三种方式显示权限:
- 单选框:如 User Type
- 下拉框:如 Access Person
- 复选框:如 Door Access和Device Access
当我们想新增加自己的权限的时候,应该怎么增加呢?odoo在这里挖了一个很大的坑,权限管理页面并没有按照传统的方式去实现,而是动态生成的。就是页面上所有的权限项目都是直接从res.groups和ir.module.category范例(model)里读取出来,然后生成动态的字段名,比如:sel_groups_59_60
因此,如果我们想增加新的权限,只需要在res.groups里追加记录就可以了。例如:
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="module_category_remotelock" model="ir.module.category">
<field name="name">Remotelock</field>
<field name="sequence">18</field>
</record>
<record id="category_remotelock_access_person" model="ir.module.category">
<field name="name">Access Person</field>
<field name="sequence">19</field>
<field name="parent_id" ref="module_category_remotelock" />
</record>
<record id="category_remotelock_access" model="ir.module.category">
<field name="name">Remotelock Access</field>
<field name="sequence">20</field>
<field name="parent_id" ref="module_category_remotelock" />
</record>
<record id="group_remotelock_door_access" model="res.groups">
<field name="name">Door Access</field>
<field name="category_id" ref="category_remotelock_access" />
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_remotelock_device_access" model="res.groups">
<field name="name">Device Access</field>
<field name="category_id" ref="category_remotelock_access" />
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_remotelock_access_guest" model="res.groups">
<field name="name">Remotelock Access Guest</field>
<field name="category_id" ref="category_remotelock_access_person" />
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_remotelock_access_user" model="res.groups">
<field name="name">Remotelock Access User</field>
<field name="category_id" ref="category_remotelock_access_person" />
<field name="implied_ids" eval="[(4, ref('group_remotelock_access_guest'))]"/>
</record>
</data>
</odoo>
这里我们定义了三个权限组Remotelock, Access Person和Remotelock Access,它们的关系是:
- Remotelock
- Access Person
- Remotelock Access
Access Person有两个权限:Remotelock Access Guest和Remotelock Access User,它们是单选关系,只能选其中一个,因此我们需要把它显示为下拉框。那么这个例子中,odoo是怎么判断这两个权限需要用下拉框显示呢?先看看odoo的代码:
@api.model
def get_groups_by_application(self):
# ...
def linearize(app, gs, category_name):
# 'User Type' is an exception
if app.xml_id == 'base.module_category_user_type':
return (app, 'selection', gs.sorted('id'), category_name)
# determine sequence order: a group appears after its implied groups
order = {g: len(g.trans_implied_ids & gs) for g in gs}
# We want a selection for Accounting too. Auditor and Invoice are both
# children of Accountant, but the two of them make a full accountant
# so it makes no sense to have checkboxes.
if app.xml_id == 'base.module_category_accounting_accounting':
return (app, 'selection', gs.sorted(key=order.get), category_name)
# check whether order is total, i.e., sequence orders are distinct
if len(set(order.values())) == len(gs):
return (app, 'selection', gs.sorted(key=order.get), category_name)
else:
return (app, 'boolean', gs, (100, 'Other'))
# ...
代码中能看到有属于类(base.module_category_user_type和base.module_category_accounting_accounting)的权限都是selection权限,即单选权限。此外,有两个条件:
- 必须属于同一个类。 比如:Remotelock Access Person和Remotelock Access User都是Access Person类
- implied_ids中定义权限个数必须不一样。 这里Remotelock Access Guest的implied_ids是’base.group_user’,而Remotelock Access User的implied_ids是group_remotelock_access_guest,即:包含了base.group_user和Remotelock Access Guest权限,数量上要多1。
不满足Selection条件的都是属于(boolean)复选权限,比如这里的Remotelock Access的两个权限:Door Access和Device Access。
那么User type的单选框是怎么显示的呢?它是被写死的,而且只有User Type类型(category_id = base.module_category_user_type)会被显示为单选框。
总结
设计最怕出乎意料,odoo的权限管理页面,为了维护上的简单,采取了这种莫名其妙的设计,而且还没有文档详细的说明,需要靠查代码才能搞清楚的,实在是糟糕透顶。而且这还带来一个问题,如果现在model的create()或write()函数中判断,用户选择了什么权限,非常困难。