Skills Development Odoo ORM Expert

Odoo ORM Expert

v20261014
odoo-orm-expert
Master Odoo ORM patterns: search, browse, create, write, domain filters, computed fields, and performance-safe query techniques. Ideal for developers building or optimizing Odoo modules.
Get Skill
445 downloads
Overview

Odoo ORM Expert

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.

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.

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.

Examples

Example 1: Search with Domain Filters

# 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)

# Note: pass dates as 'YYYY-MM-DD' strings in domains,
# NOT as fields.Date objects — the ORM serializes them correctly.

Example 2: Computed Field

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)

# Batch writes reduce repeated calls, but can trigger additional compute/tracking queries
partners = self.env['res.partner'].browse(approved_partner_ids).exists()  # Explicit scoped IDs
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

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'.

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.

Examples are model-method fragments requiring imports, record definitions and authorized scope. Do not infer missing country data means US; write only confirmed values to selected records. sudo() bypasses access rules and requires a justified boundary. Batch operations do not guarantee one SQL query, and mapped/filtered may load large recordsets; profile actual query counts and test record-rule/multi-company isolation.

Info
Category Development
Name odoo-orm-expert
Version v20261014
Size 3.84KB
Updated At 2026-10-16
Language