在 Odoo 16 中,我试图根据同一表单的其他字段的值将表单视图中的所有字段设为只读。
首先我尝试了以下方法:
<xpath expr="//field" position="attributes">
<attribute name="attrs">{'readonly': [('my_field', '=', True)]}</attribute>
</xpath>
没有结果。
我也不能使用
<form edit="false">
,因为我必须检查字段值。
带有
<field name="perm_write">1</field>
的规则可以工作,但它的行为不符合我的需要,因为它允许您修改整个表单,直到您单击 Save 并获得权限错误。
并且覆盖
get_view
不是有效的选项,因为不能依赖于 my_field
值。
我能找到的唯一解决方案是使用
xpath
修改表单的每个字段,这非常令人不安,并且如果将来通过其他应用程序将更多字段添加到表单视图中,则不一致。
有没有人有更好的解决方案?
延长
get_view
实际上是一个好主意。 OCA 的 server-ux repo 中有一个模块,其中完成了类似的操作:当将某些内容保存在 one2many 字段中时,表单视图中的每个字段都将设置为只读。为此,需要重写每个字段的 readonly 修饰符。
代码中有趣的部分:get_view
代码摘录:
@api.model
def get_view(self, view_id=None, view_type="form", **options):
res = super().get_view(view_id=view_id, view_type=view_type, **options)
View = self.env["ir.ui.view"]
# Override context for postprocessing
if view_id and res.get("base_model", self._name) != self._name:
View = View.with_context(base_model_name=res["base_model"])
if view_type == "form" and not self._tier_validation_manual_config:
# ... other stuff
# interesting part:
for node in doc.xpath("//field[@name][not(ancestor::field)]"):
if node.attrib.get("name") in excepted_fields:
continue
modifiers = json.loads(
node.attrib.get("modifiers", '{"readonly": false}')
)
if modifiers.get("readonly") is not True:
modifiers["readonly"] = OR(
[
modifiers.get("readonly", []) or [],
self._get_tier_validation_readonly_domain(),
]
)
node.attrib["modifiers"] = json.dumps(modifiers)
res["arch"] = etree.tostring(doc)
res["models"] = frozendict(all_models)
return res