Saltar al contenido
Volver al blog
DesarrolloPythonArquitectura

Anatomía de un módulo de Odoo: qué hay dentro y por qué importa

Abrimos un módulo de Odoo por dentro —manifiesto, modelos, campos, seguridad y vistas— para entender por qué casi todo se declara en lugar de programarse.

COConsultor Odoo26 de mayo de 20264 min de lectura

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

La primera vez que abrí un módulo de Odoo esperaba encontrar código. Mucho código. Bucles, controladores, plantillas HTML cosidas a mano. Lo que me encontré fue otra cosa: un puñado de archivos pequeños donde casi todo eran declaraciones. "Esto es un modelo. Tiene estos campos. Se muestra así. Lo puede ver este grupo." El motor hace el resto.

Esa es la idea que más cuesta interiorizar y, a la vez, la que explica por qué un buen módulo envejece bien. Vamos a abrir la caja pieza a pieza.

El manifiesto: el DNI del módulo

Todo módulo empieza por __manifest__.py. No tiene lógica; es la ficha de identidad que Odoo lee para saber qué cargar, en qué orden y de qué depende.

{
    "name": "Inmobiliaria",
    "version": "1.0",
    "depends": ["base", "mail"],
    "data": [
        "security/ir.model.access.csv",
        "views/property_views.xml",
        "views/property_menus.xml",
    ],
    "application": True,
    "license": "LGPL-3",
}

Aquí ya hay decisiones importantes. El orden de la lista data es el orden de carga: si una vista referencia un permiso que aún no existe, Odoo se queja. Y depends no es decorativo: declara de qué módulos parte el tuyo, y eso condiciona qué puedes heredar. Un manifiesto descuidado es la primera señal de que el resto del módulo va a doler.

Modelos: una clase de Python que se convierte en tabla

El corazón del módulo es el modelo. Una clase que hereda de models.Model y que, casi por arte de magia, se traduce en una tabla de PostgreSQL sin que escribas una sola línea de SQL.

from odoo import models, fields

class Property(models.Model):
    _name = "estate.property"
    _description = "Propiedad inmobiliaria"

    name = fields.Char(required=True)
    expected_price = fields.Float()
    bedrooms = fields.Integer(default=2)
    date_availability = fields.Date()

El _name es la identidad global del modelo dentro de todo Odoo: con él se construye la tabla (estate_property), se referencian permisos y se enlazan relaciones. El _description parece un detalle cosmético, pero Odoo lo usa en mensajes de error y avisos; omitirlo es de las cosas que delatan prisa.

El tipo de campo dice más de lo que parece

Elegir entre Char, Text, Selection o Many2one no es solo elegir cómo se guarda el dato: define cómo se valida, cómo se indexa y cómo se ve en la interfaz. Un Selection te da una lista cerrada y consistente; un Char te deja la puerta abierta a que cada usuario escriba "Madrid", "madrid" y "MADRID". Esa decisión, tomada en treinta segundos, marca la calidad de tus datos durante años.

Por eso insisto tanto a los equipos: el modelado no es la parte aburrida previa a "lo interesante". El modelado es lo interesante. Lo desarrollamos a fondo en nuestra guía de buenas prácticas para módulos.

La seguridad no es un añadido

Aquí mucha gente tropieza. En cuanto creas un modelo, Odoo necesita saber quién puede leerlo, escribirlo o borrarlo. Si no se lo dices, el modelo existe pero nadie lo ve. El mínimo viable vive en un CSV:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_property_user,property.user,model_estate_property,base.group_user,1,1,1,1

Esto es solo la mitad de la historia —los permisos a nivel de modelo—. La otra mitad, las reglas que filtran qué registros ve cada usuario, es donde se concentran los errores más caros. Le dedicamos un artículo entero: accesos vs reglas de registro.

Las vistas son XML, no plantillas

La interfaz de Odoo no se "programa". Se declara. Le dices qué campos quieres y en qué orden, y el framework dibuja el formulario, la lista o el kanban.

<record id="estate_property_view_form" model="ir.ui.view">
    <field name="name">estate.property.form</field>
    <field name="model">estate.property</field>
    <field name="arch" type="xml">
        <form>
            <sheet>
                <group>
                    <field name="name"/>
                    <field name="expected_price"/>
                    <field name="bedrooms"/>
                </group>
            </sheet>
        </form>
    </field>
</record>

Cuesta acostumbrarse si vienes de un mundo donde tú controlas cada <div>. Pero esta renuncia es justo lo que te da el panel responsive, el modo oscuro, los filtros y la edición en lote gratis. Pelearte con el framework para clavar un pixel suele salir caro; aprender a pensar en declaraciones, no.

Lo que aprendí abriendo módulos ajenos

He auditado bastantes módulos heredados, y los problemas casi nunca están en la lógica de negocio. Están en los cimientos: manifiestos con dependencias mal declaradas, campos Char donde debía haber relaciones, vistas que reescriben el formulario entero en vez de heredarlo. Cuando llega la migración a la siguiente versión, esos atajos pasan factura con intereses.

Entender la anatomía de un módulo no te convierte en desarrollador de Odoo de la noche a la mañana, pero sí te da algo más valioso: criterio para distinguir un módulo que durará de uno que será una carga. Y si vas a invertir en desarrollo a medida, ese criterio te ahorra dinero.

¿Tienes un módulo a medida que ya te da problemas en cada actualización, o un desarrollo nuevo entre manos? En una sesión de diagnóstico lo revisamos y te decimos sin rodeos si los cimientos aguantan. También puedes ver cómo abordamos el desarrollo de módulos.

#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.