Ir al contenido

QWeb para informes PDF: t-out, tablas y cabeceras

Plantilla mínima, paperformat y wkhtmltopdf en Docker
26 de junio de 2026 por
QWeb para informes PDF: t-out, tablas y cabeceras
Atemi, Aitor Atencia

Odoo · QWeb · Informes

Un informe PDF en Odoo es una plantilla QWeb que wkhtmltopdf convierte en papel. La mayoría de fallos no están en el código: están en el paperformat, en los márgenes o en que wkhtmltopdf no está instalado en el contenedor. Esta guía monta un informe mínimo y esquiva las trampas clásicas.

Logo Odoo PDF
QWeb genera HTML; wkhtmltopdf lo imprime con el paperformat indicado.

Anatomía

Las tres piezas de un informe

PiezaModeloResponsabilidad
Acción de informeir.actions.reportVincula modelo, plantilla y paperformat
Plantilla QWebir.ui.viewEl HTML con t-foreach, t-out, t-field
Paperformatreport.paperformatTamaño, márgenes, cabecera/pie

Acción

Declarar el informe

<record id="action_report_diagnostic" model="ir.actions.report">
    <field name="name">Informe de diagnóstico</field>
    <field name="model">diagnostic.test</field>
    <field name="report_type">qweb-pdf</field>
    <field name="report_name">mi_modulo.report_diagnostic</field>
    <field name="paperformat_id" ref="mi_modulo.paperformat_diagnostic"/>
    <field name="binding_model_id" ref="model_diagnostic_test"/>
</record>

binding_model_id añade el informe al menú «Imprimir» de la vista. Sin él, la acción existe pero no aparece en la UI.

Plantilla

QWeb mínimo con t-out y t-foreach

<template id="report_diagnostic">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="doc">
            <t t-call="web.external_layout">
                <div class="page">
                    <h2>Diagnóstico <span t-field="doc.name"/></h2>
                    <p>Paciente: <span t-field="doc.partner_id"/></p>
                    <table class="table">
                        <thead>
                            <tr><th>Prueba</th><th>Resultado</th></tr>
                        </thead>
                        <tbody>
                            <tr t-foreach="doc.line_ids" t-as="line">
                                <td><t t-out="line.name"/></td>
                                <td><t t-out="line.value"/></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </t>
        </t>
    </t>
</template>

Paperformat

Tamaño, márgenes y cabecera

<record id="paperformat_diagnostic" model="report.paperformat">
    <field name="name">Diagnóstico A4</field>
    <field name="format">A4</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">25</field>
    <field name="margin_bottom">20</field>
    <field name="header_spacing">15</field>
    <field name="dpi">90</field>
</record>

El margin_top debe dejar sitio a la cabecera de web.external_layout. Si el contenido pisa el logo de la empresa, sube margin_top y header_spacing.

Docker

wkhtmltopdf en el contenedor

La imagen oficial de Odoo ya incluye wkhtmltopdf con el patch de Qt. Si construyes una imagen propia, instala la versión parcheada (la de los repos de Debian/Ubuntu no sirve para cabeceras y pies).

Depuración

Errores frecuentes

SíntomaCausaSolución
PDF en blancowkhtmltopdf sin patch QtInstalar versión parcheada
Estilos no aplicanCSS fuera del bundle de informesUsar web.report_assets_common
Contenido pisa cabeceramargin_top insuficienteSubir margen y header_spacing
docs vacío en plantillareport_name mal escritoDebe ser modulo.template_id

Para depurar el HTML antes del PDF, cambia report_type a qweb-html temporalmente y abre el informe en el navegador: ves el render exacto sin la capa de wkhtmltopdf.

Resumen

Un informe = acción + plantilla QWeb + paperformat. Usa web.external_layout para cabecera/pie corporativos, t-field para formato y t-out para texto plano. El 80% de los problemas de PDF en producción son wkhtmltopdf sin patch Qt: verifícalo en el contenedor antes de tocar la plantilla.

en Odoo
OWL en Odoo 19: primer componente custom
Estructura static/src, assets en manifest y registro en el backend