odoo-orm-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Odoo ORM Expert

Odoo ORM 专家

Overview

概述

This skill teaches you Odoo's Object Relational Mapper (ORM) in depth. It covers reading/writing records, building domain filters, working with relational fields, and avoiding common performance pitfalls like N+1 queries.
本技能将深入讲解Odoo的对象关系映射(ORM)。内容涵盖记录的读写、域过滤器的构建、关联字段的使用,以及如何避免N+1查询等常见的性能陷阱。

When to Use This Skill

何时使用本技能

  • Writing
    search()
    ,
    browse()
    ,
    create()
    ,
    write()
    , or
    unlink()
    calls.
  • Building complex domain filters for views or server actions.
  • Implementing computed, stored, and related fields.
  • Debugging slow queries or optimizing bulk operations.
  • 编写
    search()
    browse()
    create()
    write()
    unlink()
    调用时。
  • 为视图或服务器操作构建复杂的域过滤器时。
  • 实现计算字段、存储字段和关联字段时。
  • 调试慢查询或优化批量操作时。

How It Works

工作方式

  1. Activate: Mention
    @odoo-orm-expert
    and describe what data operation you need.
  2. Get Code: Receive correct, idiomatic Odoo ORM code with explanations.
  3. Optimize: Ask for performance review on existing ORM code.
  1. 激活:提及
    @odoo-orm-expert
    并描述你需要的数据操作。
  2. 获取代码:获取正确、符合Odoo风格的ORM代码及解释。
  3. 优化:请求对现有ORM代码进行性能审查。

Examples

示例

Example 1: Search with Domain Filters

示例1:使用域过滤器进行搜索

python
undefined
python
undefined

Find all confirmed sale orders for a specific customer, created this year

查找特定客户今年创建的所有已确认销售订单

import datetime
start_of_year = datetime.date.today().replace(month=1, day=1).strftime('%Y-%m-%d')
orders = self.env['sale.order'].search([ ('partner_id', '=', partner_id), ('state', '=', 'sale'), ('date_order', '>=', start_of_year), ], order='date_order desc', limit=50)
import datetime
start_of_year = datetime.date.today().replace(month=1, day=1).strftime('%Y-%m-%d')
orders = self.env['sale.order'].search([ ('partner_id', '=', partner_id), ('state', '=', 'sale'), ('date_order', '>=', start_of_year), ], order='date_order desc', limit=50)

Note: pass dates as 'YYYY-MM-DD' strings in domains,

注意:在域中需将日期以'YYYY-MM-DD'字符串形式传递,

NOT as fields.Date objects — the ORM serializes them correctly.

而非fields.Date对象——ORM会正确序列化它们。

undefined
undefined

Example 2: Computed Field

示例2:计算字段

python
total_order_count = fields.Integer(
    string='Total Orders',
    compute='_compute_total_order_count',
    store=True
)

@api.depends('sale_order_ids')
def _compute_total_order_count(self):
    for record in self:
        record.total_order_count = len(record.sale_order_ids)
python
total_order_count = fields.Integer(
    string='Total Orders',
    compute='_compute_total_order_count',
    store=True
)

@api.depends('sale_order_ids')
def _compute_total_order_count(self):
    for record in self:
        record.total_order_count = len(record.sale_order_ids)

Example 3: Safe Bulk Write (avoid N+1)

示例3:安全的批量写入(避免N+1查询)

python
undefined
python
undefined

✅ GOOD: One query for all records

✅ 推荐:一次查询处理所有记录

partners = self.env['res.partner'].search([('country_id', '=', False)]) partners.write({'country_id': self.env.ref('base.us').id})
partners = self.env['res.partner'].search([('country_id', '=', False)]) partners.write({'country_id': self.env.ref('base.us').id})

❌ BAD: Triggers a separate query per record

❌ 不推荐:每条记录触发一次单独查询

for partner in partners: partner.country_id = self.env.ref('base.us').id
undefined
for partner in partners: partner.country_id = self.env.ref('base.us').id
undefined

Best Practices

最佳实践

  • Do: Use
    mapped()
    ,
    filtered()
    , and
    sorted()
    on recordsets instead of Python loops.
  • Do: Use
    sudo()
    sparingly and only when you understand the security implications.
  • Do: Prefer
    search_count()
    over
    len(search(...))
    when you only need a count.
  • Do: Use
    with_context(...)
    to pass context values cleanly rather than modifying
    self.env.context
    directly.
  • Don't: Call
    search()
    inside a loop — this is the #1 Odoo performance killer.
  • Don't: Use raw SQL unless absolutely necessary; use ORM for all standard operations.
  • Don't: Pass Python
    datetime
    /
    date
    objects directly into domain tuples — always stringify them as
    'YYYY-MM-DD'
    .
  • 建议:在记录集上使用
    mapped()
    filtered()
    sorted()
    ,而非Python循环。
  • 建议:谨慎使用
    sudo()
    ,且仅在了解其安全影响时使用。
  • 建议:当你只需要计数时,优先使用
    search_count()
    而非
    len(search(...))
  • 建议:使用
    with_context(...)
    干净地传递上下文值,而非直接修改
    self.env.context
  • 禁止:在循环内调用
    search()
    ——这是Odoo性能问题的头号元凶。
  • 禁止:除非绝对必要,否则不要使用原始SQL;所有标准操作都应使用ORM。
  • 禁止:直接将Python
    datetime
    /
    date
    对象传入域元组——始终将其格式化为
    'YYYY-MM-DD'
    字符串。

Limitations

局限性

  • Does not cover
    cr.execute()
    raw SQL
    patterns in depth — use the Odoo performance tuner skill for SQL-level optimization.
  • Stored computed fields can cause significant write overhead at scale; this skill does not cover partitioning strategies.
  • Does not cover transient models (
    models.TransientModel
    ) or wizard patterns.
  • ORM behavior can differ slightly between Odoo SaaS and On-Premise due to config overrides.
  • 不深入讲解**
    cr.execute()
    原始SQL**模式——如需SQL级别的优化,请使用Odoo性能调优技能。
  • 存储计算字段在大规模场景下会导致显著的写入开销;本技能不涉及分区策略。
  • 不涉及临时模型
    models.TransientModel
    )或向导模式。
  • 由于配置覆盖,Odoo SaaS与本地部署版本的ORM行为可能略有不同。