下面进入代码实战+源码解析:
1.表结构的搭建:
创建一个产品分类的模块:
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class TestProductType(models.Model):
_name = "test.product.type"
_description = "产品分类测试"
_rec_name = "product_type_name"
_parent_name = "parent_id"
_parent_store = True
complete_name = fields.Char(size=200, compute='_get_complete_name', store=True, string="物料分类")
product_type_code = fields.Char(size=64, required=True, string="分类编码")
product_type_name = fields.Char(size=128, required=True, string="分类名称")
parent_id = fields.Many2one('test.product.type', '物料分类上级', index=True, ondelete='restrict')
parent_path = fields.Char(index=True, unaccent=False)
child_id = fields.One2many('test.product.type', 'parent_id', 'Child Categories')
item_type = fields.Selection([
('1', '新建'),
('2', '提交'),
('3', '审核'),
('4', '封存')
], tracking=True,default='1')
@api.depends('product_type_name', 'parent_id.complete_name')
def _get_complete_name(self):
for category in self:
if category.parent_id:
category.complete_name = '%s / %s' % (category.parent_id.complete_name, category.product_type_name)
else:
category.complete_name = category.product_type_name
class TestProduct(models.Model):
_name = "test.product"
_description = "产品测试"
_rec_name = "product_name"
product_code = fields.Char(size=64, required=True, string="产品编码")
product_name = fields.Char(size=128, required=True, string="产品名称")
product_type_id = fields.Many2one('test.product.type', '产品分类', required=True)
type = fields.Selection([
('1', '新建'),
('2', '提交'),
('3', '审核'),
('4', '封存')
], default='1')
必要的三个字段:parent_id,parent_path,child_id
其中parent_path字段不能更改字段名。下面通过源码进行解释:
在odoo下面的models.py下面有下面这段注释:
上述含义为:
"_parent_store设置为True以计算parent_path字段。 除了一个parent_path字段外,还设置了一个记录树结构的索引存储,以便使用 child_of 子集和 parent_of父级 领域运算符在当前模型的记录上进行更快的分层查询。"
在models.py中,已经通过方法自动给parent_path进行赋值,不需要在对其进行二次处理。
上述含义为:
"每个记录都与一个字符串parent_path相关联,代表了从记录的根节点到该记录的路径。路径由节点ID后缀加上斜杠组成(见下面的示例)。记录的子树中的节点是那些 parent_path以该记录的 parent_path开头的节点。"
a 节点 | ID | parent_path
/ \ a | 42 | 42/
... b b | 63 | 42/63/
/ \ c | 84 | 42/63/84/
c d d | 85 | 42/63/85/
"注意:最后的斜杠 '/' 是必要的,以正确匹配子树:'42/63' 是 '42/630' 的前缀,但 '42/63/' 不是 '42/630/' 的前缀。"·
2.界面的搭建:重点在searchView里面
view源码如下:
<record id="test_product_type_filter" model="ir.ui.view">
<field name="name">test.product.type.search</field>
<field name="model">test.product.type</field>
<field name="arch" type="xml">
<search string="产品类别">
<field name="product_type_code"/>
<field name="product_type_name"/>
<field name="parent_id"/>
<field name="item_type"/>
<searchpanel>
<field name="item_type" enable_counters="1"/>
<field name="parent_id" filter_domain="[('child_id', '!=', False)]" text="name" limit="1000" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<record model="ir.actions.act_window"
id="action_test_product_type">
<field name="name">产品分类</field>
<field name="res_model">test.product.type</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="test_product_type_filter"/>
</record>
对应好上下级关系即可达到树状检索效果。