odoo child_of, parent_of 理解

该操作符是用于多层继承结构的查询,和in不同,

我们有如下表格product.category,parent_id 外键关联到自身的表格,可以设置记录之间的层级关系.

 id | parent_path |       name       |            complete_name             | parent_id |
----+-------------+------------------+--------------------------------------+-----------+
  1 | 1/          | All              | All                                  |           |
  2 | 1/2/        | Saleable         | All / Saleable                       |         1 |
  3 | 1/3/        | Expenses         | All / Expenses                       |         1 |
  4 | 1/4/        | Internal         | All / Internal                       |         1 |
  5 | 1/2/5/      | Services         | All / Saleable / Services            |         2 |
  6 | 1/2/5/6/    | Saleable         | All / Saleable / Services / Saleable |         5 |
  7 | 1/2/7/      | Software         | All / Saleable / Software            |         2 |
  8 | 1/2/8/      | Office Furniture | All / Saleable / Office Furniture    |         2 |
  9 | 1/9/        | Consumable       | All / Consumable                     |         1 |
(9 行记录)

假如我要查询id=2 的所有子记录(包含子记录的子记录),就可以使用child_of 操作符:

categ = self.env.get('product.category').browse(2)
categ.search([('id', 'child_of', categ.id)]).ids
# [2, 8, 5, 6, 7]

同理,也可以查询某一条记录的所有父记录,

目前还明白算法是怎样实现的,但是算法的代码应该如下:

        def child_of_domain(left, ids, left_model, parent=None, prefix=''):
            """ Return a domain implementing the child_of operator for [(left,child_of,ids)],
                either as a range using the parent_path tree lookup field
                (when available), or as an expanded [(left,in,child_ids)] """
            if not ids:
                return FALSE_DOMAIN
            if left_model._parent_store:
                doms = OR([
                    [('parent_path', '=like', rec.parent_path + '%')]
                    for rec in left_model.browse(ids)
                ])
                if prefix:
                    return [(left, 'in', left_model.search(doms).ids)]
                return doms
            else:
                parent_name = parent or left_model._parent_name
                child_ids = set(ids)
                while ids:
                    ids = left_model.search([(parent_name, 'in', ids)]).ids
                    child_ids.update(ids)
                return [(left, 'in', list(child_ids))]

        def parent_of_domain(left, ids, left_model, parent=None, prefix=''):
            """ Return a domain implementing the parent_of operator for [(left,parent_of,ids)],
                either as a range using the parent_path tree lookup field
                (when available), or as an expanded [(left,in,parent_ids)] """
            if left_model._parent_store:
                parent_ids = [
                    int(label)
                    for rec in left_model.browse(ids)
                    for label in rec.parent_path.split('/')[:-1]
                ]
                if prefix:
                    return [(left, 'in', parent_ids)]
                return [('id', 'in', parent_ids)]
            else:
                parent_name = parent or left_model._parent_name
                parent_ids = set()
                for record in left_model.browse(ids):
                    while record:
                        parent_ids.add(record.id)
                        record = record[parent_name]
                return [(left, 'in', list(parent_ids))]
posted @ 2020-03-02 01:01  那时一个人  阅读(1822)  评论(0编辑  收藏  举报