《Odoo10 Development Essentials》Chapter5(p106)中介绍了Odoo中分层关系的建立。 代码如下
class Tags(models.Model):
_name = 'todo.task.tag'
...
_parent_store = True
parent_id = fields.Many2one('todo.task.tag', 'Parent Tag',
ondelete='restrict')
parent_left = fields.Integer('Parent Left', index=True)
parent_right = fields.Integer('Parent Right', index=True)
在上面的代码中。
- 使用
parent_id
字段来关联上层记录。 - 使用
_parent_store = True
这个属性来开启分层搜索功能. - 使用
parent_left
和parent_right
字段来进行记录所属层级,当时看书的时候对这些代码不是很理解,只是知道这样做能够提高层级关系数据模型查询数据记录的效率。
简单原理
查询分层结构记录时,一般的想到的方法是从根目录开始,对每个子目录进行递归查询.然后才能得出具体的分层结构。(如递归查询文件夹文件)
Odoo中为了提高层次结构(树状结构)查询效率,每一条层级数据记录添加parent_left
跟parent_right
字段.
假设A是B的上级对象。那么存在这样的逻辑关系。
B.parent_right > A.parent_left
B.parent_left > A.parent_left
B.parent_right < A.parent_right
B.parent_left < A.parent_right
画个图来理解下
- 可以看到,图中的B属于A的,清楚的表示了A,B的层级从属关系。
Odoo 应用
我们用Odoo11的product模块作为演示
在/addons/product/models/product.py
文件中.看到产品目录(ProductCategory类.15行起)的代码
class ProductCategory(models.Model):
_name = "product.category"
_description = "Product Category"
_parent_name = "parent_id"
_parent_store = True
_parent_order = 'name'
_rec_name = 'complete_name'
_order = 'parent_left'
name = fields.Char('Name', index=True, required=True, translate=True)
complete_name = fields.Char(
'Complete Name', compute='_compute_complete_name',
store=True)
parent_id = fields.Many2one('product.category', 'Parent Category', index=True, ondelete='cascade')
child_id = fields.One2many('product.category', 'parent_id', 'Child Categories')
parent_left = fields.Integer('Left Parent', index=1)
parent_right = fields.Integer('Right Parent', index=1)
添加parent_L/R
数值
All (0, 11)
----Internal (1, 2)
----Saleable (3,10)
----Service (6,7)
----Physical (4,5)
----Software (8,9)
- 通过上面的展示,可以清楚的看到所有产品目录各自的包含结构。根目录为All,然后依次为Internal,Saleable. Saleable下面又有3个子目录…
假设要找到All产品目录下的所有产品目录
demo=# select id,name from product_category where parent_left > 0 and parent_right < 11;
id | name
----+----------
3 | Internal
6 | Physical
5 | Software
2 | Saleable
4 | Service
(5 rows)
- 只需要一条查询语句即可找到所有子目录.无须遍历.
要找Saleable下的所有子目录即可使用
parent_left > 3 and parent_right < 10
作为条件
结论:
在Odoo的实际使用中,发现使用parent存储特性的模块主要涉及account, product, stock_location. 因为这个优化对查询层级结构效率有良好效果。 凡事皆有两面,这种存储特性会在数据库中添加多余的字段。其实是以空间换时间。
参考
https://stackoverflow.com/questions/11861436/parent-left-and-parent-right-in-openerp