El Framework ORM de Odoo
El ORM (Object Relational Mapping) de Odoo es el núcleo que conecta las clases de Python con la base de datos PostgreSQL. Permite definir modelos, campos escalares y relacionales, reglas de validación y consultas sin tener que escribir sentencias SQL manuales.
1. Definición de Modelos y Tipos de Campos #
Un modelo se define creando una clase que hereda de models.Model:
1from odoo import models, fields, api 2 3class LibraryBook(models.Model): 4 _name = 'library.book' # Identificador interno del modelo (tabla SQL: library_book) 5 _description = 'Registro de Libros' 6 _order = 'name asc, publication_date desc' 7 8 # Campos escalares 9 name = fields.Char(string='Título', required=True, index=True) 10 isbn = fields.Char(string='ISBN', size=13) 11 description = fields.Text(string='Sinopsis') 12 pages = fields.Integer(string='Número de Páginas') 13 price = fields.Float(string='Precio de Venta', digits=(8, 2)) 14 state = fields.Selection([ 15 ('draft', 'Borrador'), 16 ('available', 'Disponible'), 17 ('borrowed', 'Prestado'), 18 ('lost', 'Extraviado'), 19 ], string='Estado', default='draft', required=True) 20 publication_date = fields.Date(string='Fecha de Publicación') 21 is_available = fields.Boolean(string='Disponible para Préstamo', default=True) 22 23 # Campos relacionales 24 partner_id = fields.Many2one('res.partner', string='Editorial', ondelete='restrict') 25 tag_ids = fields.Many2many('library.tag', string='Etiquetas') 26 loan_ids = fields.One2many('library.loan', 'book_id', string='Historial de Préstamos')
2. Métodos del Ciclo de Vida CRUD y Decoradores @api #
En Odoo moderno (v16/v17/v18), la creación en lote (batch creation) es el estándar mediante @api.model_create_multi:
1class LibraryBook(models.Model): 2 _inherit = 'library.book' 3 4 # Campo calculado con decorador @api.depends 5 discounted_price = fields.Float( 6 string='Precio con Descuento', 7 compute='_compute_discounted_price', 8 store=True 9 ) 10 11 @api.depends('price') 12 def _compute_discounted_price(self): 13 for record in self: 14 record.discounted_price = record.price * 0.90 15 16 # Sobrescritura del método create estándar 17 @api.model_create_multi 18 def create(self, vals_list): 19 for vals in vals_list: 20 if not vals.get('name'): 21 vals['name'] = 'Libro Sin Título' 22 return super().create(vals_list) 23 24 # Validación de negocio con @api.constrains 25 @api.constrains('pages') 26 def _check_pages(self): 27 for record in self: 28 if record.pages and record.pages <= 0: 29 raise models.ValidationError('El número de páginas debe ser un entero positivo.')
3. Consultas y Manipulación de Recordsets #
Odoo utiliza el objeto self.env para acceder a cualquier modelo y realizar operaciones seguras con dominios de filtrado:
1# 1. Búsqueda con dominios (AND implícito) 2books = self.env['library.book'].search([ 3 ('state', '=', 'available'), 4 ('price', '<', 50.0) 5]) 6 7 # 2. Búsqueda con operadores lógicos OR ('|') en notación polaca inversa 8discounted_books = self.env['library.book'].search([ 9 '|', 10 ('price', '<', 20.0), 11 ('state', '=', 'draft') 12]) 13 14 # 3. Acceso directo por ID 15single_book = self.env['library.book'].browse(1) 16if single_book.exists(): 17 single_book.write({'state': 'borrowed'})
4. Manipulación Relacional Moderna con Command #
Para crear o modificar registros en relaciones One2many y Many2many de forma limpia y legible, Odoo proporciona la clase Command:
1from odoo import Command 2 3self.env['res.partner'].browse(10).write({ 4 'category_id': [ 5 Command.create({'name': 'Cliente VIP'}), # Crea un nuevo tag (antiguo (0, 0, {...})) 6 Command.link(5), # Asocia el tag con ID 5 (antiguo (4, 5)) 7 Command.unlink(3), # Desasocia el tag con ID 3 (antiguo (3, 3)) 8 Command.delete(2), # Elimina de la BDD el registro ID 2 (antiguo (2, 2)) 9 ] 10})
Resumen del tema
Conceptos clave #
- Modelos (
models.Model): clases Python que representan tablas relacionales en PostgreSQL identificadas mediante_name. - Tipos de Campos (
odoo.fields): escalares (Char,Text,Integer,Float,Boolean,Date,Datetime,Selection) y relacionales (Many2one,One2many,Many2many). - Ciclo de Vida CRUD: métodos
create(vals_list)con@api.model_create_multi,write(vals)yunlink(). - Decoradores
@api:@api.dependspara campos computados,@api.constrainspara validaciones lógicas y@api.onchangepara dinamismo en vistas de formulario. - Manipulación Relacional (
Command): sintaxis modernaCommand.create(),Command.link(),Command.unlink()yCommand.delete().
Qué debes recordar #
El ORM de Odoo mapea clases Python a tablas de PostgreSQL, permitiendo extender modelos existentes con _inherit y manipular recordsets con search, create, write y decoradores @api.