Saltar al contenido
Volver al blog
DesarrolloPythonArquitectura

Herencia en Odoo: la función que decide si tu código sobrevive a las actualizaciones

Extensión clásica, delegación y herencia de vistas. Las tres formas de modificar Odoo sin tocar el core —y por qué heredar en vez de copiar te ahorra cada migración.

COConsultor Odoo30 de mayo de 20264 min de lectura

Forma parte de nuestra guía completa: Desarrollo de módulos en Odoo.

Si tuviera que quedarme con una sola idea para explicar por qué unos Odoo envejecen bien y otros se convierten en una pesadilla, sería esta: la herencia. Es el mecanismo que te deja añadir, modificar y ampliar casi cualquier cosa de Odoo —un modelo del core, una vista estándar, un método de negocio— sin tocar el código original. Y "sin tocar el original" no es una preferencia estética: es lo único que hace que tu desarrollo sobreviva cuando Odoo saca la siguiente versión.

El problema es que "herencia" en Odoo significa tres cosas distintas, y mezclarlas es fuente constante de confusión. Vamos a separarlas.

1. Extensión clásica: añadir a algo que ya existe

Es la que usarás el 90% del tiempo. Declaras _inherit con el nombre de un modelo existente y, sin crear una tabla nueva, le añades campos, métodos o sobreescribes su comportamiento.

from odoo import models, fields

class SaleOrder(models.Model):
    _inherit = "sale.order"

    delivery_zone = fields.Char(string="Zona de reparto")

Eso solo ya añade una columna a sale.order y la deja disponible en todo el sistema. La parte interesante llega cuando quieres intervenir en la lógica, por ejemplo al confirmar un pedido:

    def action_confirm(self):
        # tu lógica antes...
        res = super().action_confirm()
        # tu lógica después...
        for order in self:
            order.message_post(body="Pedido confirmado y zona asignada.")
        return res

Ese super() es sagrado. Es lo que llama al método original de Odoo (y al de cualquier otro módulo que también lo haya extendido). Olvidarlo —o no devolver su resultado— es uno de los bugs más sutiles y desesperantes que existen: de repente "deja de funcionar algo que no tocaste". Tocaste el flujo sin darte cuenta.

2. Delegación: "es un" sin copiar

La segunda forma es menos habitual pero brillante cuando encaja. Con _inherits (ojo, con s al final) tu modelo delega en otro: por debajo guarda un enlace al modelo padre y expone todos sus campos como si fueran suyos. El ejemplo canónico es res.users, que delega en res.partner:

class Member(models.Model):
    _name = "club.member"
    _inherits = {"res.partner": "partner_id"}

    partner_id = fields.Many2one("res.partner", required=True, ondelete="cascade")
    membership_number = fields.Char()

Ahora un socio "tiene" nombre, email y teléfono sin que tú los declares, porque vive sobre un contacto. La diferencia con la extensión clásica es clave: con _inherit modificas el modelo existente; con _inherits creas un modelo nuevo que reutiliza otro por composición. Confundir _inherit y _inherits es un clásico; míralo siempre dos veces.

3. Herencia de vistas: cambiar la interfaz sin reescribirla

La tercera no toca Python: toca XML. Es la que más se hace mal. En lugar de copiar el formulario entero del core y editarlo (un suicidio de cara a las actualizaciones), apuntas con precisión quirúrgica al sitio donde quieres insertar tu campo, usando xpath y position.

<record id="view_order_form_inherit" model="ir.ui.view">
    <field name="name">sale.order.form.delivery</field>
    <field name="model">sale.order</field>
    <field name="inherit_id" ref="sale.view_order_form"/>
    <field name="arch" type="xml">
        <xpath expr="//field[@name='payment_term_id']" position="after">
            <field name="delivery_zone"/>
        </xpath>
    </field>
</record>

"Después del campo payment_term_id, mete el mío." Eso es todo. Cuando Odoo actualice ese formulario en la próxima versión, tu añadido se reaplica encima, intacto. El que copió la vista entera, en cambio, se queda con una versión congelada del formulario de hace dos años y pierde todo lo nuevo. Lo vemos en cada migración: el módulo que "heredó bien" sube en horas; el que "copió y pegó" cuesta días.

La regla que repetimos hasta el cansancio: hereda, no copies

Todo esto se reduce a un principio que ya mencionamos en las buenas prácticas para módulos: duplicar lógica del core es deuda técnica con fecha de caducidad. La fecha es el día de la próxima actualización. Heredar cuesta un poco más de pensar al principio y se paga solo en cada salto de versión.

Mi recomendación práctica, después de bastantes migraciones: antes de escribir nada, pregúntate "¿esto ya existe en Odoo de alguna forma?". Casi siempre la respuesta es sí, y casi siempre lo correcto es extenderlo, no reinventarlo. Si entiendes esto y lo del super(), evitas la mayoría de los problemas que nos llegan en auditorías.

Por qué esto te importa aunque no programes

Si eres quien decide, la herencia explica una frase que oirás mucho: "esto es personalizable, pero hay que hacerlo bien". Un desarrollo que hereda es un activo que evoluciona contigo; uno que copia y parchea es una bomba de relojería que estalla en la siguiente versión y te ata a quien lo escribió. Saber distinguir uno de otro —o tener a alguien que lo sepa— es lo que separa un Odoo que crece de uno que se estanca.

¿Tienes módulos a medida y te preocupa cómo aguantarán la próxima actualización? En una auditoría de tu código revisamos si heredan como deben o si te espera una sorpresa. Y si vas a desarrollar desde cero, así lo hacemos en nuestro servicio de desarrollo a medida. Para los cimientos, empieza por la anatomía de un módulo y las relaciones entre modelos.

#Desarrollo#Python#Arquitectura
Compartir artículo

Comentarios (0)

Sé el primero en comentar.

Inicia sesión para dejar un comentario.

Acceder

Los comentarios se revisan antes de publicarse.

¿Listo para sacarle el máximo partido a Odoo?

Cuéntanos tu reto. En una primera llamada de 30 minutos te diremos cómo Odoo puede ayudarte, sin compromiso.