Odoo ORM框架完全指南:数据模型设计与查询优化技巧

Odoo ORM框架完全指南:数据模型设计与查询优化技巧

【免费下载链接】odoo Odoo. Open Source Apps To Grow Your Business. 【免费下载链接】odoo 项目地址: https://gitcode.com/GitHub_Trending/od/odoo

Odoo ORM(对象关系映射)是Odoo框架的核心组件,它允许开发者使用Python对象操作数据库,而无需编写原始SQL。本文将从数据模型设计到查询优化,全面讲解Odoo ORM的使用技巧,帮助开发者构建高效、可维护的业务应用。

数据模型基础

模型定义

在Odoo中,数据模型通过Python类定义,继承自models.Model。每个模型对应数据库中的一个表,类属性对应表字段。

from odoo import models, fields, api

class Product(models.Model):
    _name = 'product.product'  # 模型唯一标识
    _description = 'Product'   # 模型描述
    
    name = fields.Char(string='Name', required=True)
    price = fields.Float(string='Price')
    category_id = fields.Many2one('product.category', string='Category')

模型定义文件通常位于模块的models目录下,如addons/product/models/product.py

字段类型

Odoo提供了丰富的字段类型,满足不同业务需求:

字段类型说明示例
Char字符类型name = fields.Char(string='Name')
Integer整数类型quantity = fields.Integer(string='Quantity')
Float浮点类型price = fields.Float(string='Price', digits=(10, 2))
Boolean布尔类型is_active = fields.Boolean(string='Active', default=True)
Date日期类型start_date = fields.Date(string='Start Date')
Datetime日期时间类型create_date = fields.Datetime(string='Create Date')
Many2one多对一关系category_id = fields.Many2one('product.category', string='Category')
One2many一对多关系product_ids = fields.One2many('product.product', 'category_id', string='Products')
Many2many多对多关系tag_ids = fields.Many2many('product.tag', string='Tags')

详细的字段类型说明可参考Odoo官方文档

高级模型设计

模型继承

Odoo支持三种模型继承方式:

  1. 经典继承:通过_inherit扩展现有模型
class Product(models.Model):
    _inherit = 'product.product'
    
    barcode = fields.Char(string='Barcode')
  1. 委托继承:通过_inherits实现模型组合
class Product(models.Model):
    _name = 'product.product'
    _inherits = {'product.template': 'product_tmpl_id'}
    
    product_tmpl_id = fields.Many2one('product.template', required=True, ondelete='cascade')
  1. 原型继承:通过_abstract创建抽象模型
class Base(models.AbstractModel):
    _name = 'base.abstract'
    _description = 'Base Abstract Model'
    
    name = fields.Char(string='Name')

class Product(models.Model):
    _name = 'product.product'
    _inherit = 'base.abstract'

计算字段

使用compute属性定义计算字段,通过@api.depends指定依赖字段:

class Product(models.Model):
    _name = 'product.product'
    
    price = fields.Float(string='Price')
    tax = fields.Float(string='Tax')
    total = fields.Float(string='Total', compute='_compute_total', store=True)
    
    @api.depends('price', 'tax')
    def _compute_total(self):
        for record in self:
            record.total = record.price + record.tax

store=True表示计算结果将存储在数据库中,适用于频繁查询的场景。

数据查询操作

基本查询

Odoo ORM提供了多种查询方法:

# 搜索所有记录
products = self.env['product.product'].search([])

# 带条件搜索
expensive_products = self.env['product.product'].search([('price', '>', 100)])

# 搜索一条记录
product = self.env['product.product'].search([('id', '=', 1)], limit=1)

# 按ID浏览记录
product = self.env['product.product'].browse(1)

# 计数
count = self.env['product.product'].search_count([('price', '>', 100)])

高级查询

域名过滤

使用复杂域名实现高级过滤:

# 价格在100-200之间,且分类为'电子产品'
products = self.env['product.product'].search([
    ('price', '>=', 100),
    ('price', '<=', 200),
    ('category_id.name', '=', '电子产品')
])

# 逻辑或条件
products = self.env['product.product'].search([
    '|',
    ('price', '>', 200),
    ('category_id.name', '=', '电子产品')
])
排序和分页
# 按价格降序排列,取前10条
products = self.env['product.product'].search([], order='price desc', limit=10, offset=0)
字段筛选

指定需要返回的字段,减少数据传输:

products = self.env['product.product'].search_read(
    [('price', '>', 100)],
    fields=['name', 'price', 'category_id']
)

查询优化技巧

索引优化

为频繁查询的字段添加索引:

class Product(models.Model):
    _name = 'product.product'
    
    name = fields.Char(string='Name', index=True)
    barcode = fields.Char(string='Barcode', index=True)
    
    _sql_constraints = [
        ('barcode_unique', 'unique(barcode)', 'Barcode must be unique!')
    ]
    
    _indexes = [
        ('name', 'barcode'),  # 复合索引
    ]

预加载数据

使用prefetch方法减少数据库查询:

# 预加载分类数据
products = self.env['product.product'].search([])
products.prefetch('category_id')

for product in products:
    print(product.category_id.name)  # 不会触发额外查询

使用with_context

通过上下文控制查询行为:

# 忽略记录的active字段过滤
products = self.env['product.product'].with_context(active_test=False).search([])

# 设置时区
products = self.env['product.product'].with_context(tz='Asia/Shanghai').search([])

批量操作

使用createwrite的批量操作提高性能:

# 批量创建
self.env['product.product'].create([
    {'name': 'Product 1', 'price': 100},
    {'name': 'Product 2', 'price': 200},
])

# 批量更新
products = self.env['product.product'].search([])
products.write({'price': products.price * 1.1})

性能优化最佳实践

避免N+1查询问题

使用search_read代替search后遍历:

# 低效
products = self.env['product.product'].search([])
for product in products:
    print(product.category_id.name)  # 每条记录触发一次查询

# 高效
products = self.env['product.product'].search_read([], ['name', 'category_id'])
for product in products:
    print(product['category_id'][1])  # 已预加载分类名称

使用exists()检查记录有效性

product = self.env['product.product'].browse(1)
if product.exists():
    # 记录存在
    pass
else:
    # 记录不存在
    pass

使用sudo()获取权限

# 获取管理员权限执行操作
self.env['product.product'].sudo().create({'name': 'Admin Product'})

总结

Odoo ORM提供了强大而灵活的数据操作能力,合理使用模型设计和查询优化技巧,可以显著提升应用性能。建议开发者深入理解ORM的工作原理,结合业务场景选择合适的实现方式。

更多Odoo ORM高级特性,请参考Odoo开发者文档

延伸学习

通过不断实践和探索,您将能够充分利用Odoo ORM构建高效、可靠的业务系统。

【免费下载链接】odoo Odoo. Open Source Apps To Grow Your Business. 【免费下载链接】odoo 项目地址: https://gitcode.com/GitHub_Trending/od/odoo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值