Odoo11升级至16:配置字段控制员工字段只读权限问题求助
Odoo 16升级后字段权限控制失效的修复方案
在将Odoo从11版本升级到16版本后,原有的字段权限控制逻辑失效:通过res.config.settings的editable_fields多对多字段指定可编辑字段,让非hr.group_hr_manager组用户无法编辑其他字段(设为只读)的代码不再生效。以下是针对该问题的修复方案:
问题根源分析
- 多对多字段关联错误:原
res.config.settings中多对多字段的中间表关联字段定义错误,导致配置的可编辑字段无法正确存储和读取。 - 配置读取方式过时:Odoo16中
ir.default读取多对多字段值的方式兼容性下降,建议使用官方推荐的配置读取方法。 - 视图修饰符处理逻辑不兼容: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
相关产品推荐
相关产品推荐

