odoo18开发手册--树形字段 Tree

 1.基本结构定义

from odoo import api, fields, models

class ProductCategory(models.Model):
    _name = 'product.category'
    _description = '产品分类'
    _parent_store = True
    _parent_path = True  # Odoo 18新特性
    
    name = fields.Char(string='名称', required=True)
    parent_id = fields.Many2one('product.category', string='上级分类')
    child_ids = fields.One2many('product.category', 'parent_id', string='下级分类')
    parent_path = fields.Char(index=True)  # 新的父级路径字段

2.新特性 - parent_path

# 替代了早期版本的parent_left/parent_right
parent_path = fields.Char(index=True)

# parent_path存储格式示例: "1/2/3/"
# 表示当前记录的完整父级路径

3.树形视图定义

<record id="view_category_tree" model="ir.ui.view">
    <field name="name">product.category.tree</field>
    <field name="model">product.category</field>
    <field name="arch" type="xml">
        <tree>
            <field name="display_name"/>
            <field name="parent_id"/>
            <field name="sequence" widget="handle"/>
        </tree>
    </field>
</record>

4.常用功能实现

class ProductCategory(models.Model):
    _name = 'product.category'
    _description = '产品分类'
    _parent_store = True
    _parent_path = True
    _order = 'sequence, name'

    # 基本字段
    name = fields.Char(required=True)
    sequence = fields.Integer(default=10)
    parent_id = fields.Many2one('product.category', index=True)
    child_ids = fields.One2many('product.category', 'parent_id')
    parent_path = fields.Char(index=True)

    # 计算完整名称
    complete_name = fields.Char(
        compute='_compute_complete_name', 
        store=True, 
        recursive=True
    )

    @api.depends('name', 'parent_id.complete_name')
    def _compute_complete_name(self):
        for record in self:
            if record.parent_id:
                record.complete_name = f'{record.parent_id.complete_name} / {record.name}'
            else:
                record.complete_name = record.name
                
    # 检查循环引用
    @api.constrains('parent_id')
    def _check_hierarchy(self):
        if not self._check_recursion():
            raise ValidationError('Error! You cannot create recursive categories.')

5.高级查询操作

def action_find_categories(self):
    # 获取所有子分类
    child_categories = self.env['product.category'].search([
        ('parent_path', 'like', f'{self.parent_path}%')
    ])
    
    # 获取所有父分类
    parent_ids = [int(x) for x in self.parent_path.split('/')[:-1]]
    parent_categories = self.env['product.category'].browse(parent_ids)
    
    # 获取同级分类
    sibling_categories = self.env['product.category'].search([
        ('parent_id', '=', self.parent_id.id),
        ('id', '!=', self.id)
    ])

6.安全权限设置

<record id="category_comp_rule" model="ir.rule">
    <field name="name">Product Category Multi-Company</field>
    <field name="model_id" ref="model_product_category"/>
    <field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>

7.新增功能示例

class ProductCategory(models.Model):
    _name = 'product.category'
    
    # 统计子分类数量
    child_count = fields.Integer(
        compute='_compute_child_count',
        string='子分类数量'
    )
    
    # 分类层级
    level = fields.Integer(
        compute='_compute_level',
        string='层级'
    )
    
    @api.depends('child_ids')
    def _compute_child_count(self):
        for record in self:
            record.child_count = len(record.child_ids)
            
    @api.depends('parent_path')
    def _compute_level(self):
        for record in self:
            record.level = len(record.parent_path.split('/')) - 1

8.实用工具方法

def get_hierarchy_data(self):
    """获取完整的层级数据"""
    return {
        'id': self.id,
        'name': self.name,
        'level': self.level,
        'child_count': self.child_count,
        'children': [child.get_hierarchy_data() for child in self.child_ids],
    }

def move_to_category(self, target_category_id):
    """移动分类到指定位置"""
    self.ensure_one()
    if target_category_id:
        target = self.browse(target_category_id)
        if target.parent_path.startswith(self.parent_path):
            raise ValidationError('不能移动到子分类下')
    self.parent_id = target_category_id

9.性能优化建议

  • 使用parent_path索引提高查询效率
  • 适当使用预加载(prefetch)
  • 大数据量时考虑分批处理
  • 合理使用递归计算字段
  • 避免过深的层级结构

10.注意事项

  • parent_path字段会自动维护
  • 注意处理循环引用问题
  • 考虑多公司情况下的数据隔离
  • 注意树形结构的深度限制
  • 合理使用序列号控制显示顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

odoo实施

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值