最近在使用odoo14的时候,发现odoo的attr里面对于attrs={"invisible":[('state','=','draft'),('sponsor','=',uid)]} 这种写法并不支持,期初以为是自己语法有问题,后来反复查验之后发现不是语法的问题,而是odoo14默认在attrs属性里面不支持对于uid这种变量的解析,所以在执行编译的时候会报错。
那么,如果我们想要实现这种在当前用uid进行比较实现隐藏的效果,应该如何处理呢?
经过我反复试验和验证之后,发现之所以不能通过uid进行比较是因为在odoo的底层控制没有实现对uid这个参数的兼容,所以就导致了这一问题,通过重写代码可以实现这一效果,具体的路径是在:
把代码做如下更改,便可支持兼容uid,
def transfer_node_to_modifiers(node, modifiers, context=None, current_node_path=None):
# Don't deal with groups, it is done by check_group().
# Need the context to evaluate the invisible attribute on tree views.
# For non-tree views, the context shouldn't be given.
if node.get('attrs'):
# 解决attrs 不能解析uid属性的问题
if 'uid' in node.get('attrs'):
if context.get('uid', False):
user_id = str(context.get('uid', False))
attrs = node.get('attrs')
node.set('attrs', attrs.replace('uid', user_id))
else:
# 通过user_id设定初始值来让用户有权限对模块进行升级等操作
user_id = '1'
attrs = node.get('attrs')
node.set('attrs', attrs.replace('uid', user_id))
modifiers.update(ast.literal_eval(node.get('attrs')))
if node.get('states'):
if 'invisible' in modifiers and isinstance(modifiers['invisible'], list):
# TODO combine with AND or OR, use implicit AND for now.
modifiers['invisible'].append(('state', 'not in', node.get('states').split(',')))
else:
modifiers['invisible'] = [('state', 'not in', node.get('states').split(','))]
for a in ('invisible', 'readonly', 'required'):
if node.get(a):
v = bool(safe_eval.safe_eval(node.get(a), {'context': context or {}}))
node_path = current_node_path or ()
if 'tree' in node_path and 'header' not in node_path and a == 'invisible':
# Invisible in a tree view has a specific meaning, make it a
# new key in the modifiers attribute.
modifiers['column_invisible'] = v
modifiers['tree_invisible'] = v
elif v or (a not in modifiers or not isinstance(modifiers[a], list)):
# Don't set the attribute to False if a dynamic value was
# provided (i.e. a domain from attrs or states).
modifiers[a] = v
这样修改了之后,便可以支持attrs里面用uid进行表达式的与或计算等。
但是,直接修改底层代码或多或少会有一些风险,所以这个地方,通过研究发现可以使用另外一种替代方案,通过添加一个字段,使用compute属性来判断当前条件是否满足,然后在attrs里面通过计算True 或者 FALSE来判断是否满足。
比如说,我要控制某个按钮只有在申请人在草稿状态下才可见 。那么如何实现呢?
1. 在py文件里面,首先添加一个字段,
is_current_login_approval = fields.Boolean("登录用户是否当前处理人", store=False, compute='_compute_current_approval')
2.实现这个compute方法:
@api.depends('current_approval')
def _compute_current_approval(self):
# 注 我们这里的审批人(current_approval)是一个Many2many
for flow in self:
if not flow.current_approval:
flow.is_current_login_approval = False
return
for record in flow.current_approval:
if self.env.context.get('uid',None) == record.id:
flow.is_current_login_approval = True
return
else:
flow.is_current_login_approval = False
3.在attrs里面就可以使用这个compute计算出来的字段来进行计算了
最后实现的效果,就是在to_approve以及approving状态,只有当前审批人可以看到”同意“的按钮。
---------------------------------------------------------------------------------- 总结 ---------------------------------------------------------------------------------
目前为止,odoo14原生的代码并不支持在attrs里面,直接使用uid进行计算(domain表达式里面支持),但是可以通过新引入一个compute field 计算出对应的值,然后就可以获取到了,或者您也可以在评估好了
相应的风险之后,直接像上面这样修改底层的代码来更快的实现。
(如果您觉得我的文章对您有用的话,还请动一下您的小手,帮我点一个关注吧)。^_^
---------------------------------------------------------------------------------- end ---------------------------------------------------------------------------------