Inside the ORM: How Odoo Executes Your Recordset Operations
Introduction
In the world of Odoo development, working with data almost always means working with recordsets. Whether you’re retrieving records with search(), creating new entries with create(), updating values with write(), or removing records with unlink(), these operations form the backbone of any module you build.
While the syntax is clean and intuitive, these methods are powered by Odoo’s Object Relational Mapping (ORM) — a sophisticated engine that manages database communication, enforces security, handles caching, and triggers business logic automatically
ORM in Odoo
ORM stands for Object Relational Mapping — a programming technique that lets you interact with a database using Python objects and methods instead of writing raw SQL queries.
In Odoo, the ORM is the layer between your Python code and the underlying PostgreSQL database. When you run a request:
The ORM will:
Interpret your request (the model name, search domain, and options).
Translate it into optimized SQL that PostgreSQL understands.
Execute the SQL query via the database cursor.
Wrap the results in Python recordset objects, ready for you to use.
Example
partners = self.env['res.partner'].search([('is_company', '=', True)], limit=2)
print(partners)
1️. Interpret your request
Model name: res.partner
Domain: [('is_company', '=', True)]
Options: limit=2 (return max 2 records)
2️. Translate it into optimized SQL
SELECT id
FROM res_partner
WHERE is_company = true
ORDER BY id
LIMIT 2;
3️. Execute the SQL query via the database cursor
self._cr.execute("SELECT id FROM res_partner WHERE is_company = %s ORDER BY id LIMIT 2",(True,))
ids = [row[0] for row in self._cr.fetchall()]
fetched IDs: [3, 5]
4. Wrap the results in Python recordset objects
partners = self.env['res.partner'].browse([3, 5])
print(partners)
Output: res.partner(3, 5)
How ORM optimizes for performance:
Prefetching – When you access one field of multiple records, Odoo loads that field for all records in one query.
Lazy loading – Fields not needed immediately are fetched only when accessed.
Caching – Recently accessed records and computed values are stored in memory for faster reuse during the same request.
Batch operations – Operations like write() and unlink() can handle multiple records at once, avoiding repetitive SQL calls.
Common ORM Methods
Method | Purpose | Example |
search() | Retrieve matching records | self.env['res.partner'].search([('name','=','ABC')]) |
create() | Insert new records | self.env['res.partner'].create({'name': 'ABC'}) |
write() | Update existing records | partner.write({'email': 'abc@example.com'}) |
unlink() | Delete records | partner.unlink() |
Conclusion
The ORM is the backbone of Odoo’s modular architecture. By understanding its inner workings, you can write better-performing, cleaner, and more secure code. Whether you’re a beginner creating your first model or an experienced developer optimizing a high-load application, mastering the ORM will make your development process smoother and more efficient.