Curso odoo (Módulos)

3.1. Definición de modelos

En Odoo, un modelo representa una tabla en la base de datos y se crea como una clase de Python que hereda de models.Model. Cada modelo se encarga de definir:

  1. Nombre interno del modelo (por ejemplo, my.module o res.partner).
  2. Campos que indican la estructura de los datos.
  3. Comportamientos y restricciones de negocio.

Ejemplo básico de definición de un modelo

Supongamos que queremos crear un modelo para almacenar libros en una biblioteca. Creamos un archivo en la carpeta models/ llamado library_book.py con el siguiente contenido:

1from odoo import models, fields
2
3class LibraryBook(models.Model):
4    _name = 'library.book'  # Nombre interno que identifica la tabla en la BDD
5    _description = 'Library Book'
6
7    name = fields.Char(string='Title', required=True)
8    author = fields.Char(string='Author')
9    description = fields.Text(string='Description')
10    publication_date = fields.Date(string='Publication Date')
11    is_available = fields.Boolean(string='Is Available?', default=True)
  • _name: Define el identificador interno del modelo. Este nombre se usará para referencias en otras partes (vistas, herencia, etc.).
  • _description: Texto que describe la finalidad del modelo.
  • fields.X: Campos definidos con tipos específicos:
    • Char: Texto corto.
    • Text: Texto largo.
    • Date: Campo de fecha.
    • Boolean: Valor verdadero o falso.
    • … entre otros muchos tipos (Integer, Float, Many2one, Many2many, One2many, etc.).

Nota: Además de models.Model, existen otras clases base como models.TransientModel (para wizards) y models.AbstractModel (para crear lógica reutilizable), pero en la mayoría de los casos empezarás con models.Model.


3.2. Herencia de modelos existentes

En muchos casos, querrás extender la funcionalidad de un modelo ya existente en Odoo en lugar de crear uno desde cero. Existen dos maneras principales de hacerlo:

  1. Herencia por extensión:
    Se utiliza cuando deseas agregar campos o métodos a un modelo ya existente.

    1from odoo import models, fields
    2
    3class LibraryBookInherit(models.Model):
    4    _inherit = 'library.book'  # Referenciamos el modelo que queremos heredar
    5
    6    isbn = fields.Char(string='ISBN')
    7    copies = fields.Integer(string='Number of Copies', default=1)

    Aquí, seguimos trabajando sobre la misma tabla de library.book, añadiendo nuevas columnas (isbn, copies).

  2. Herencia delegada (_inherits):
    Se utiliza cuando creas un nuevo modelo que “hereda” los campos y métodos de otro modelo, pero cada uno sigue teniendo su propia tabla en la base de datos. Esto es útil si necesitas unir funcionalidades de distintos modelos, pero manteniendo tablas separadas.

    1class NewModel(models.Model):
    2    _name = 'new.model'
    3    _inherits = {'library.book': 'book_id'}
    4
    5    book_id = fields.Many2one('library.book', ondelete='cascade')
    6    additional_field = fields.Char(string='Extra Field')

En ambos casos, tu objetivo es reutilizar o ampliar la lógica existente sin duplicar código ni crear modelos que hagan lo mismo.


3.3. Métodos en el modelo

Además de los campos, un modelo puede tener métodos que contienen la lógica de negocio. Algunos métodos clave:

  • create(vals): Controla lo que ocurre al crear un registro nuevo.
  • write(vals): Controla lo que pasa al escribir (actualizar) un registro existente.
  • unlink(): Se ejecuta al eliminar un registro.
  • Métodos con decoradores:
    • @api.model: Métodos que no dependen de un registro en particular (no llevan self ligado a un registro en la base de datos).
    • @api.depends: Se utiliza para campos calculados, indicando de qué campos depende el cálculo.
    • @api.onchange: Permite modificar campos de un formulario en tiempo real cuando otro campo cambia.

Ejemplo de un método create

1from odoo import models, fields, api
2
3class LibraryBook(models.Model):
4    _name = 'library.book'
5    _description = 'Library Book'
6
7    name = fields.Char(string='Title', required=True)
8    author = fields.Char(string='Author')
9
10    @api.model
11    def create(self, vals):
12        # Lógica antes de crear el registro
13        if not vals.get('name'):
14            vals['name'] = 'Untitled Book'
15        
16        record = super(LibraryBook, self).create(vals)
17        
18        # Lógica después de crear el registro (si se requiere)
19        # ...
20        
21        return record

En este ejemplo, comprobamos si en los valores (vals) no viene el título (name); si no existe, se asigna “Untitled Book”. Después, se llama a super() para que la creación real en la base de datos ocurra de manera estándar.


3.4. Búsqueda y lectura de registros

Para buscar (leer) registros en Odoo, se usan métodos como search(), browse(), read(), entre otros. Estos métodos aceptan dominios (listas de tuplas) que especifican condiciones.

1# Ejemplo de dominio básico
2books = self.env['library.book'].search([('author', '=', 'Miguel de Cervantes')])
  • self.env['library.book'] es la manera de obtener el “entorno” para realizar la búsqueda en el modelo library.book.
  • El dominio [('author', '=', 'Miguel de Cervantes')] indica que queremos todos los libros donde el campo author sea exactamente “Miguel de Cervantes”.
  • El resultado books será un recordset (conjunto de registros). Puedes iterar sobre ellos o acceder a sus campos.

Uso de browse() y read()

  • browse(): Carga registros de la base de datos a partir de un ID o lista de IDs, sin aplicar un dominio.
    1book = self.env['library.book'].browse(1)
    2if book.exists():
    3    print(book.name)
  • read(): Retorna los valores de los campos en forma de lista de diccionarios, útil para exportar datos o procesarlos sin la lógica adicional del recordset.
    1values = book.read(['name', 'author'])
    2# values podría resultar en [{'id': 1, 'name': 'El Ingenioso Hidalgo...', 'author': 'Miguel de Cervantes'}]

Dominios y contextos

  • Dominios (domain): Sirven para filtrar la búsqueda (por ejemplo, “libros con fecha posterior a 2020”).
  • Contextos (context): Se utilizan para pasar información adicional que pueda afectar el comportamiento de ciertas operaciones (por ejemplo, definir una moneda específica o un idioma).

Ejemplo: self.with_context(lang='es_ES').search([...]) para establecer un contexto de idioma antes de la búsqueda.


Conclusión de la Parte 3

  1. Un modelo en Odoo se define mediante una clase Python que hereda de models.Model.
  2. Puedes extender modelos existentes usando _inherit o _inherits.
  3. Los métodos (create, write, unlink, entre otros) te permiten personalizar la lógica de cómo se crean, modifican o eliminan registros.
  4. Para buscar registros, utilizas métodos como search(), browse(), read(), con la opción de usar dominios para filtrar y contextos para ajustar la forma en que se ejecutan las operaciones.

Con este conocimiento, estás listo para profundizar en el uso de vistas (formularios, listas, etc.) en Odoo, que será el siguiente paso lógico al crear cualquier módulo con interfaz de usuario. ¡Continuemos avanzando en el desarrollo de módulos personalizados!

  • Loading...