转载:http://book.odoomommy.com/chapter5/README12.html
再谈Onchange
对于onchange方法,相信很多写过代码的同学已经很熟悉了,那么为什么这里要单独列出一章来讲述且放到了第三部分中?这是因为看似简单的onchange内部实际并不简单,想要真正认识清楚onchange同学还是需要费一番周折的。
回顾
我们先来回顾一下onchange的用法:
一如既往的的简单,逻辑也很清晰。但是这里隐藏着一个坑,就是要求计算中的字段出现在视图中,并且不可以是只读的。如果被设置的字段不在视图中或者被设置为了只读,你会发现onchange方法第一次失效了。
为什么会这样,这就要从onchange的工作原理说起了。
内部机制
阅读源码是理解onchange本质的最佳方法,本书使用的是odoo13版本中的代码(是的,不用怀疑,onchange虽然比较底层,但是官方还是在每个版本中进行了各种修改)。
先来看onchange的定义:
def onchange(self, values, field_name, field_onchange):
""" Perform an onchange on the given field.
:param values: dictionary mapping field names to values, giving the
current state of modification
:param field_name: name of the modified field, or list of field
names (in view order), or False
:param field_onchange: dictionary mapping field names to their
on_change attribute
"""
pass
注释写得很简单,values是一个字典,包含了发生变化得字段得名字和值,field_name是发生变化的字段名或者列表,field_onchange 属性中指定了on_change方法的字段名称字典。其实内部有些坑,官方并没有在任何文档中说明。
对于 One2many类型的字段而言,从onchange返回给前段的结果分析,第一条永远是(5,)。这就意味着,Odoo再更新One2many类型的字段时,并非直接更新其字段的值,而是先删除然后新增了一条。注意这里的新增,并非一定是创建,还有可能是关联。
与之对应的是,Onchange再操作时,并不直接操作原有记录,而是复制了一份,这就是为什么,你在onchange方法中操作one2many字段时,打印出来的永远是一个NewId