Odoo15按条件隐藏编辑按钮 ir.rule配置不生效问题解决
Odoo15 按自定义条件隐藏表单编辑按钮实现方案
你之前写的ir.rule配置不生效,核心是三个点写错了:
- ir.rule里的
perm_read/perm_write等参数是规则的生效范围标记,不是给匹配到的记录设置权限。你把perm_write设为False,相当于这条规则根本不会参与写入权限的校验流程,配了也不会执行。 - domain逻辑和字段都写错了。ir.rule的domain是圈定「这条规则要作用在哪些记录上」,Odoo里记录创建人默认字段是
create_uid,不存在名为user的标准字段,而且直接写字符串'john'根本匹配不到系统里的用户记录。 - Odoo的表单编辑按钮显示逻辑完全依赖当前用户对打开记录的写权限,只要后端权限校验正确拦截写权限,按钮会自动隐藏,不需要额外改前端样式去隐藏。
方案一:纯记录规则实现(无自定义Python代码,适配你的需求)
直接替换你原来的ir.rule配置即可,逻辑是:指定用户组的用户,访问John创建的患者记录时,没有写权限:
<record id="hideEdit_rule" model="ir.rule"> <field name="name">Restrict Edit For John's Patient Records</field> <field name="model_id" ref="model_hospital_patient" /> <!-- 圈定规则作用范围:所有创建人为John的记录 --> <field name="domain_force">[('create_uid', '=', ref('base.user_john'))]</field> <field name="groups" eval="[(4, ref('om_hospital.hospital_management_pratisyen_doctor'))]"/> <!-- 权限标记:读、写、删除校验都走这条规则,创建操作不涉及已有记录,不参与规则校验 --> <field name="perm_read" eval="True"/> <field name="perm_write" eval="True"/> <field name="perm_create" eval="False"/> <field name="perm_unlink" eval="True"/> </record>
注意:如果你的环境里John用户的xmlid不是
base.user_john,可以换成你实际环境里的用户xmlid,或者临时用[('create_uid.name', '=', 'John')]做名称匹配,但生产环境优先用xmlid关联,避免重名导致规则失效。配置完升级模块,用户打开John创建的记录时,编辑按钮会自动隐藏,同时后端会拦截所有非法的写入请求,不会有越权漏洞。
方案二:前端动态控制(适配更复杂的自定义判断逻辑)
如果你的判断条件比「创建人是John」更复杂,比如要结合记录状态、审批节点、当前时间等多维度判断,可以结合计算字段+视图attrs实现,注意这个方案必须配合后端权限校验,不能只做前端隐藏:
- 先在hospital.patient模型里加计算字段,判断当前用户是否有编辑权限:
from odoo import models, fields, api class HospitalPatient(models.Model): _inherit = 'hospital.patient' can_edit_record = fields.Boolean(compute='_compute_can_edit_record') @api.depends('create_uid', 'state') # 把你判断逻辑依赖的字段都加到depends里 def _compute_can_edit_record(self): john_user = self.env.ref('base.user_john') for rec in self: # 这里可以写任意自定义判断逻辑 if rec.create_uid == john_user and self.env.user != john_user: rec.can_edit_record = False else: rec.can_edit_record = True
- 继承表单视图,给form标签加编辑权限的attrs控制:
<record id="view_patient_form_hide_edit" model="ir.ui.view"> <field name="name">hospital.patient.hide.edit</field> <field name="model">hospital.patient</field> <field name="inherit_id" ref="om_hospital.view_hospital_patient_form"/> <field name="arch" type="xml"> <xpath expr="//form" position="attributes"> <attribute name="attrs">{'edit': [('can_edit_record', '=', True)]}</attribute> </xpath> </field> </record>
提醒:这个方案只是前端隐藏按钮,必须同时配置对应的后端写入拦截(要么用方案一的ir.rule,要么重写write方法加权限判断),否则用户可以直接通过RPC接口绕过前端修改数据。
内容的提问来源于stack exchange,提问作者Enes Kara
相关产品推荐
相关产品推荐

