Odoo ORM框架完全指南:数据模型设计与查询优化技巧
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支持三种模型继承方式:
- 经典继承:通过
_inherit扩展现有模型
class Product(models.Model):
_inherit = 'product.product'
barcode = fields.Char(string='Barcode')
- 委托继承:通过
_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')
- 原型继承:通过
_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([])
批量操作
使用create和write的批量操作提高性能:
# 批量创建
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构建高效、可靠的业务系统。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



