Introducción
Al empezar a desarrollar sobre Odoo, te topas pronto con un concepto clave: la herencia de modelos. El ORM de Odoo está pensado para que unos modelos aprovechen la estructura y los datos de otros sin duplicar código ni tablas innecesarias, lo que facilita ampliar la aplicación sin romper la coherencia de la base de datos.
Los campos heredados son la pieza que hace posible esa reutilización. Permiten que un modelo muestre y manipule atributos definidos físicamente en otro modelo como si fuesen suyos, con el beneficio de mantener la información centralizada y evitar inconsistencia entre módulos.
Esta guía describe qué son los campos heredados, las tres formas de herencia de modelos que los generan, cómo se almacenan y resuelven en la base de datos, y cuándo conviene emplearlos en personalizaciones reales de Odoo.
¿Qué es un campo heredado en Odoo?
En el marco del ORM de Odoo, decimos que un campo está heredado cuando un modelo accede a atributos definidos en otro mediante alguno de los mecanismos de herencia que Odoo soporta. En lugar de volver a declarar el campo, el modelo hijo lo reutiliza y lo expone como propio.
Eso contribuye a un modelo de datos compacto y consistente. Por ejemplo, el nombre de un contacto se mantiene en un único lugar y aparece donde haga falta —presupuestos, facturas o oportunidades— porque todos leen de la misma fuente de verdad.
Las tres formas de herencia en Odoo
Odoo distingue tres modos de heredar modelos, y cada uno gestiona los campos de manera distinta según el objetivo estructural que se persiga.
1. Herencia clásica
Es el patrón más habitual: se utiliza _inherit sin declarar un nuevo _name. Con él extiendes directamente un modelo existente, añadiendo campos o métodos sobre la misma tabla de la base de datos. No se crea una tabla nueva: los campos añadidos se incorporan al modelo original.
Así es como la mayoría de los módulos introducen campos en modelos estándar. Por ejemplo, un módulo CRM puede añadir atributos a res.partner y esos campos conviven en la misma tabla que los del core.
2. Herencia por prototipo
Cuando combinas _inherit con _name estás copiando la estructura del modelo padre para crear uno nuevo con su propia tabla. Los campos del padre se replican en la tabla del hijo y las modificaciones en uno no afectan al otro.
Este enfoque se usa menos en personalizaciones cotidianas, pero sirve cuando necesitas un nuevo tipo de registro que comparte la estructura de otro sin ser el mismo objeto.
3. Herencia por delegación
La más característica se declara con _inherits. El modelo hijo mantiene un enlace Many2one al padre y expone sus campos como si fuesen suyos. Los datos residen en la tabla del padre; el hijo actúa como una vista combinada de campos propios y delegados.
Cuando la gente habla estrictamente de campos heredados, suele referirse a este tipo: no hay duplicado del dato, sino acceso relacional en lectura y escritura hacia el registro padre.
Un ejemplo habitual en Odoo es la relación entre res.users y res.partner. Cada usuario es también un contacto: nombre, correo y teléfono se guardan en el partner y el usuario los muestra vía delegación.
Cómo funciona el campo
Herencia por delegación: cómo funciona internamente
Al usar _inherits, el ORM crea un puente transparente entre dos tablas. Al leer un campo heredado en el hijo, Odoo sigue el Many2one hacia el registro padre y devuelve el valor almacenado allí.
Al escribir sobre ese campo desde el hijo, Odoo actualiza el registro del padre. Para el desarrollador el campo parece nativo; para la base de datos, el dato vive en la tabla del padre.
De ello se deriva una consecuencia práctica: no hay duplicación de datos. Si cambias el nombre en el partner, ese cambio se refleja inmediatamente en todas las entidades que lo referencian, incluido el usuario que hereda de él.
Herencia clásica y la base de datos
Con herencia clásica, los campos nuevos se añaden a la tabla del modelo original; no hay tablas extra. En la base de datos, el modelo extendido y el original coinciden, lo que hace de esta técnica la forma más limpia y común para añadir atributos en proyectos de personalización.
Campos related: herencia ligera y práctica
Un campo related es una variante de campo computado que lee su valor siguiendo una cadena de relaciones hacia otro registro. No es exactamente lo mismo que la herencia de modelos, pero se usa a menudo para exponer datos remotos sin alterar la estructura del modelo actual.
Por ejemplo, en un pedido de venta puedes crear partner_country_id que lea partner_id.country_id. En la vista se comporta como si fuera un campo propio del pedido, pero el valor proviene del partner.
Los campos related pueden guardarse en la base de datos con store=True, lo que acelera búsquedas y filtros a costa de ocupar espacio y requerir recomputación cuando cambia la fuente.
Cómo se resuelven los campos en tiempo de ejecución
Cuando Odoo carga la definición de un modelo, calcula el mapa completo de campos, incluidos los heredados. Al arrancar, el servidor ya tiene mapeados los orígenes de cada campo —si vienen de la propia tabla, de una tabla padre por delegación o de una cadena related— y esa información se cachea para rendimiento.
Casos prácticos en la empresa
Más allá de la técnica, los campos heredados resuelven problemas reales de negocio al mantener la información coherente entre módulos sin replicarla.
1. CRM y ventas: la ficha de contacto
Cuando un comercial crea una oportunidad, los datos de contacto —nombre, teléfono, correo— provienen del partner enlazado. Si el partner actualiza su teléfono, esa modificación se refleja en leads, presupuestos y pedidos relacionados sin intervención manual.
Aquí confluyen herencia clásica y campos related: el módulo CRM extiende res.partner con atributos propios, y los pedidos muestran la información de contacto mediante campos related.
2. Productos y variantes
En productos, Odoo aplica delegación para gestionar variantes. product.product usa _inherits con product.template. Los atributos comunes a todas las variantes —nombre, categoría, precio— residen en la plantilla; los específicos (por ejemplo, código de barras) quedan en la variante.
Gracias a esto puedes tener decenas de variantes de una prenda compartiendo nombre y descripción sin almacenar esos valores repetidos en la base de datos.
3. Usuarios y contactos
Cada usuario del sistema es también un contacto: res.users hereda de res.partner mediante _inherits = {'res.partner': 'partner_id'}, por lo que datos como el correo o la dirección se mantienen sincronizados entre la ficha de usuario y la agenda de contactos.
4. Inventario: movimientos y datos de producto
Las líneas de movimiento muestran descripciones y datos que vienen de la plantilla de producto mediante campos relacionados. Los responsables de almacén ven información actualizada en las listas de picking sin que el módulo de inventario duplique los datos del producto.
5. Contabilidad: líneas de factura
Las líneas contables referencian productos y partners. El nombre del producto, las cuentas y las configuraciones fiscales se obtienen desde los modelos de producto y partner mediante relaciones y campos related, garantizando que la información vista por contabilidad coincide con la configurada por ventas.
Crear o personalizar campos heredados
Personalización con Odoo Studio
Odoo Studio permite añadir campos y modificar vistas sin tocar Python. Bajo el capó, Studio aplica herencia clásica: extiende el modelo añadiendo el campo a su definición y gestionando la migración de la base de datos.
Studio también permite crear campos related. Al seleccionar "Campo relacionado" puedes señalar cualquier ruta relacional accesible desde el modelo actual —por ejemplo, en pedidos leer el país o el NIF del partner— y colocarlo en formularios o listados.
Para usuarios funcionales y consultores, Studio suele ser la herramienta adecuada: gestiona nombres, migraciones y ubicación en vistas sin necesidad de desarrollo.
Personalización técnica en Python
Para desarrolladores, los campos heredados se declaran en Python mediante la clase models.Model del ORM de Odoo.
Ejemplo de herencia clásica para añadir un campo personalizado:
class CrmLead(models.Model):
_inherit = 'crm.lead'
x_contract_value = fields.Float(
string='Estimated Contract Value'
)
Ejemplo de herencia por delegación para crear un nuevo modelo que comparte campos de otro:
class EmployeeProfile(models.Model):
_name = 'hr.employee.profile'
_inherits = {'res.partner': 'partner_id'}
partner_id = fields.Many2one(
'res.partner',
required=True,
ondelete='cascade'
)
employee_id = fields.Many2one(
'hr.employee',
string='Employee'
)
Ejemplo de campo related para mostrar un valor de un registro enlazado:
class SaleOrder(models.Model):
_inherit = 'sale.order'
partner_country_id = fields.Many2one(
related='partner_id.country_id',
string='Customer Country',
store=True
)
Vía API XML-RPC (configuración remota)
También es posible crear campos programáticamente mediante la API XML-RPC de Odoo y el modelo ir.model.fields. Este método replica lo que hace Studio y resulta útil para automatizar despliegues sin acceso directo al servidor.
Para añadir un campo related por API se crea un registro en ir.model.fields con el tipo correcto y el parámetro related que define la ruta. Es una técnica habitual en procesos de configuración automatizada.
Buenas prácticas
Elige el tipo de herencia adecuado
Usa herencia clásica cuando sólo quieras añadir campos o métodos a un modelo existente: es la opción más simple y segura. Reserva la delegación para cuando realmente necesites dos conjuntos de registros vinculados, por ejemplo cuando un concepto empresarial extiende a un contacto sin ser exactamente un contacto.
Prefiere campos related para acceso de sólo lectura
Si sólo necesitas mostrar un valor de un registro enlazado en formularios o listados, un campo related suele ser más limpio que crear una herencia por delegación: evita dependencias estructurales adicionales y es más fácil de mantener.
Precaución con store=True en campos related
Almacenar un campo related acelera búsquedas y filtros, pero convierte el valor en una copia. Odoo recomputa cuando cambia la fuente, pero en casos límite puede desincronizarse. Usa store=True sólo si realmente necesitas filtrar o agrupar por ese campo a gran escala.
Siempre prefija los campos personalizados con x_
Cualquier campo que añadas a un modelo estándar debería comenzar por x_ (o emplear el namespace del módulo) para evitar colisiones con campos que Odoo pueda introducir en futuras versiones.
Documenta la cadena de herencia
En personalizaciones complejas deja notas que expliquen el origen de los campos y el motivo. Un campo llamado x_country_code en pedido puede no dejar claro su vínculo con partner_id.country_id.code sin documentación.
Gestiona correctamente los borrados en cascada
Con delegación, el registro padre se crea automáticamente al crear el hijo; al borrar el hijo lo habitual es borrar también el padre. Define ondelete='cascade' en el Many2one de _inherits para evitar registros huérfanos.
Errores habituales
Confundir los tres tipos de herencia
El error más frecuente entre desarrolladores nuevos es usar _inherit junto con _name cuando querían extender el modelo. Eso genera un modelo nuevo en lugar de modificar el existente. Revisa la definición: si no quieres un nuevo modelo, omite _name.
No crear el registro padre al usar _inherits
En delegación, el padre no siempre se crea automáticamente en todos los flujos. Si generas el hijo vía API o scripts, asegúrate de permitir que el ORM cree el padre o crea el padre primero y pasa su ID; omitirlo provoca errores de integridad en la base de datos.
Intentar cambiar el tipo de un campo mediante herencia
Odoo no permite redefinir el tipo de un campo existente a través de herencia. Puedes ajustar etiquetas, dominios o ayuda, pero no cambiar, por ejemplo, un Char a Integer. Intentarlo provocará fallos al instalar el módulo.
Abusar de related almacenados
Marcar cada campo related con store=True puede parecer una estrategia de rendimiento, pero inflará la base de datos y aumentará la carga de recomputaciones. Si el campo origen cambia con frecuencia, los related almacenados generan mucho trabajo adicional. Aplica esta opción con criterio.
Suponer que los campos heredados respetan las reglas de acceso del hijo
Los campos heredados por delegación residen en el modelo padre; los permisos del modelo hijo no se aplican automáticamente al nivel de la tabla padre. Si limitas el acceso al hijo pero no al padre, los usuarios podrían leer esos campos accediendo al padre directamente. Revisa las reglas de seguridad en ambos modelos cuando uses delegación.
Conclusión
Los campos heredados no son una curiosidad técnica: forman parte de la arquitectura de Odoo. Relaciones como usuario–contacto, variante–plantilla o pedido–datos de cliente dependen de este mecanismo para mantener la información coherente y evitar duplicación.
Saber qué tipo de herencia emplear, cuándo usar un campo related y cómo se comportan estos mecanismos en la base de datos te convertirá en un personalizador de Odoo más eficaz. Escribirás código más limpio, diseñarás modelos de datos mejores y perderás menos tiempo depurando comportamientos inesperados.
La idea clave es sencilla: el ORM de Odoo favorece que los campos vivan en un único lugar y sean accedidos desde muchos puntos. Ese principio —campos centralizados y accesibles— es lo que mantiene coherente el modelo de datos a medida que la aplicación crece con múltiples módulos interconectados.
¿Necesitas ayuda con tu implantación de Odoo?
En Dasolo acompañamos a empresas en la implantación, personalización y optimización de Odoo. Tanto si necesitas desarrollar un módulo a medida, ampliar modelos estándar o entender por qué tu modelo de datos se comporta de forma inesperada, nuestro equipo aporta experiencia práctica para acelerar el proyecto y evitar fallos costosos.
Si tienes dudas sobre tu modelo de datos en Odoo, la estrategia de campos personalizados o la implementación técnica, estaremos encantados de analizar tu caso y ofrecer recomendaciones. Contacta con nosotros y encontremos la solución adecuada para tu proyecto.