Odoo · Vistas · XML
Las vistas XML definen la UX del backend. IDs inconsistentes, xpath frágiles y olvidar la vista search provocan errores al actualizar módulos (-u) y pantallas rotas en producción. Convenciones claras ahorran horas de depuración.
Convenciones
IDs y nombres de archivo
| Elemento | Patrón | Ejemplo |
|---|---|---|
| Vista form | view_<modelo>_form | view_diagnostic_test_form |
| Vista list | view_<modelo>_list | view_diagnostic_test_list |
| Vista kanban | view_<modelo>_kanban | view_diagnostic_test_kanban |
| Vista search | view_<modelo>_search | view_diagnostic_test_search |
| Acción | action_<modelo> | action_diagnostic_test |
| Menú | menu_<nombre> | menu_diagnostic_root |
Un archivo por modelo (diagnostic_test_views.xml) o por tipo si crece mucho. Evita IDs genéricos como view_form — colisionan entre módulos.
Form
Formulario: sheet, header y chatter
<record id="view_diagnostic_test_form" model="ir.ui.view">
<field name="name">diagnostic.test.form</field>
<field name="model">diagnostic.test</field>
<field name="arch" type="xml">
<form>
<header>
<field name="state" widget="statusbar"
statusbar_visible="pending,in_progress,done"/>
</header>
<sheet>
<group>
<field name="partner_id"/>
<field name="subject_id"/>
<field name="professional_id"/>
</group>
</sheet>
<chatter/>
</form>
</field>
</record>
<list> (antes <tree> en versiones antiguas).
List y kanban
Listas y tableros
<record id="view_diagnostic_test_list" model="ir.ui.view">
<field name="arch" type="xml">
<list decoration-info="state == 'pending'"
decoration-warning="state == 'in_progress'">
<field name="name"/>
<field name="partner_id"/>
<field name="state" widget="badge"/>
</list>
</field>
</record>
<record id="view_diagnostic_test_kanban" model="ir.ui.view">
<field name="arch" type="xml">
<kanban default_group_by="state">
<field name="state"/>
<templates>
<t t-name="card">
<field name="name"/>
</t>
</templates>
</kanban>
</field>
</record>
Search
Filtros, agrupaciones y search panel
<record id="view_diagnostic_test_search" model="ir.ui.view">
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="partner_id"/>
<filter string="Pending" name="pending"
domain="[('state', '=', 'pending')]"/>
<group expand="0" string="Group By">
<filter string="State" name="group_state"
context="{{'group_by': 'state'}}"/>
</group>
</search>
</field>
</record>
Sin vista search, el usuario pierde filtros rápidos. Los name en filters permiten referenciarlos en acciones (context={'search_default_pending': 1}).
Herencia
xpath: específico y reversible
<record id="view_sale_order_form_diagnostic" model="ir.ui.view">
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_id']" position="after">
<field name="diagnostic_test_ids" readonly="1"/>
</xpath>
</field>
</record>
| ❌ Evitar | ✅ Preferir |
|---|---|
position="replace" en nodos grandes | inside / after puntuales |
| xpath sobre índices frágiles | Atributos @name, @string estables |
| Herencia múltiple del mismo nodo | Un xpath por módulo, orden en manifest |
-u mi_modulo y revisar modo debug → Edit View.groups= en lugar de xpath condicional complejo cuando puedas.
Resumen
Nombra vistas y acciones de forma predecible, define form/list/search/kanban como bloque mínimo, hereda con xpath específicos y prueba cada -u en staging. Las vistas son código: merecen revisión en PR igual que Python.