You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo11升级至16:配置字段控制员工字段只读权限问题求助

Odoo 16升级后字段权限控制失效的修复方案

在将Odoo从11版本升级到16版本后,原有的字段权限控制逻辑失效:通过res.config.settings的editable_fields多对多字段指定可编辑字段,让非hr.group_hr_manager组用户无法编辑其他字段(设为只读)的代码不再生效。以下是针对该问题的修复方案:

问题根源分析

  1. 多对多字段关联错误:原res.config.settings中多对多字段的中间表关联字段定义错误,导致配置的可编辑字段无法正确存储和读取。
  2. 配置读取方式过时:Odoo16中ir.default读取多对多字段值的方式兼容性下降,建议使用官方推荐的配置读取方法。
  3. 视图修饰符处理逻辑不兼容:Odoo16对视图渲染的modifiers处理更严格,原代码的遍历和修改方式存在遗漏或错误。

修复后的完整代码

from odoo import models, fields, api
import json
from lxml import etree

class HrEmployeeResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    # 修正多对多中间表的关联字段定义,确保外键指向正确
    editable_fields = fields.Many2many(
        'ir.model.fields', 
        'editable_fields_rel', 
        'res_config_settings_id',  # 中间表中指向当前res.config.settings的外键
        'field_id',                # 中间表中指向ir.model.fields的外键
        string='Editable Field', 
        domain="[('model_id.model', '=', 'hr.employee')]"  # 修正domain,用model_id.model匹配模型
    )

    @api.model
    def get_values(self):
        res = super(HrEmployeeResConfigSettings, self).get_values()
        # 读取可编辑字段配置,存入结果
        editable_fields = self.env['ir.default'].get('res.config.settings', 'editable_fields')
        res.update(editable_fields=editable_fields)
        return res

    def set_values(self):
        super(HrEmployeeResConfigSettings, self).set_values()
        # 保存可编辑字段配置到ir.default
        self.env['ir.default'].set('res.config.settings', 'editable_fields', self.editable_fields.ids)

class CustomEmployee(models.Model):
    _inherit = 'hr.employee'

    def fields_view_get(self, view_id=None, view_type="form", toolbar=False, submenu=False):
        res = super(CustomEmployee, self).fields_view_get(
            view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
        )
        # 仅在表单视图中处理权限
        if view_type != 'form':
            return res

        # 获取配置的可编辑字段列表
        config = self.env['res.config.settings'].get_values()
        editable_field_ids = config.get('editable_fields', [])
        editable_fields = self.env['ir.model.fields'].browse(editable_field_ids).mapped('name')

        # 非HR经理组用户才需要设置只读
        if not self.env.user.has_group('hr.group_hr_manager') and editable_fields:
            doc = etree.XML(res['arch'])
            # 遍历所有非可编辑字段,设置只读
            for field_name in res['fields']:
                if field_name not in editable_fields:
                    # 查找视图中所有该字段的节点
                    nodes = doc.xpath(f"//field[@name='{field_name}']")
                    for node in nodes:
                        # 设置readonly属性
                        node.set('readonly', '1')
                        # 处理modifiers
                        modifiers = json.loads(node.get('modifiers', '{}'))
                        modifiers['readonly'] = True
                        node.set('modifiers', json.dumps(modifiers))
            # 更新视图架构
            res['arch'] = etree.tostring(doc, encoding='unicode')

        return res

关键修复点说明

  • 多对多字段修正:调整中间表的关联字段为res_config_settings_id和field_id,确保配置能正确存储;同时修正domain条件为model_id.model,Odoo16中ir.model.fields的model_id关联ir.model,需要通过model字段匹配模型名称。
  • 配置读写优化:重写get_values和set_values方法,确保配置的读取和保存符合Odoo16的规范,避免直接使用ir.default的兼容性问题。
  • 视图处理优化:增加视图类型判断,仅在表单视图中应用权限控制;遍历字段时更精准,处理modifiers时默认空字典,避免解析错误;使用f-string提升代码可读性。

内容的提问来源于stack exchange,提问作者Pawan Kumar Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:52:45