openerp child_of操作符深度解析
child_of
此操作符,从代码来看,等价于:
[('x','child_of',id)] ==> x.prarent_left >=id.parent_left && x.parent_left <= id.parent_right , 求x(的集合)。 为了形象的说明,我们一步步来:
首先,模型定义里面必需要有parent_left / parent_right ,才支持在这个模型上执行 child_of 操作(odoo硬编码,不要问我为什么),如下:
model
(
'parent_left': ....,
'parent_right':...,
)
定义了之后,必需有其他模型many2one到此模型,假设模型A m2o 到 model,这个字段叫做 model_id,那么可以在A上用 [('model_id','child_of',id)] 得到一个A的model_id是以上x的集合的A的对象集合。这么说有些拗口,我们看看例子。
openerp中恰好有不少例子,producct.category 和 product.product就分别对应上面的model和A。
product.product 有一个字段m2o到 product.category,这个字段叫做 categ_id,如下
在仓库/产品/产品类别 中,我们可以点击一个类别,进入对应的产品列表,这就是一个child_of的实例, 其表达式是 [('categ_id','child_of',context['search_default_categ_id'])],如下:
这个表达式用在引用模型A上,此处是product.product。得到的结果就是一个product list, 其categ_id满足表达式:
[('categ_id','child_of',id)] ==> categ_id.prarent_left >=id.parent_left && categ_id.parent_left <= id.parent_right , 求categ_id(的集合)。
得到[categ_id]后,再用 product.categ_id in [categ_id]进行过滤。
parent_left / parent_righ
首先,这两玩意是硬编码支持child_of运算的,没啥好说,位于:openerp/osv/expression.py (703 ~ 724)
是通用父子关系的一种硬编码。工作原理:采用数轴包含关系来区分父子。如下图:
添加子节点算法:
第一句,把邻居的左脚统一右移
第二句,把长辈和邻居的右脚统一右移
最后,自己占沙发
删除算法则相反。
以上,py代码部分完。js代码部分尚未解析。
后来,无意中发现,原来这个算法还是有些来头的,名为MPTT(modified preordered tree traversal),可以参考下这里。http://www.sitepoint.com/hierarchical-data-database-2/