跳至内容

Odoo 19 报表继承开发手册

Odoo 19 报表继承概述

适用版本:Odoo 19、Odoo企业版、Odoo社区版

Odoo的报表引擎基于QWeb构建,这套基于XML的模板系统同样支撑着系统网页视图。和视图一样,报表也支持继承功能:你可以通过自定义模块对原生报表进行扩展或修改,无需改动系统核心代码。这一点对于保障定制内容在版本升级后正常可用至关重要。

本文将详细讲解Odoo 19中报表继承的实现方式,从基础用法到实际落地场景逐一说明。

Odoo中所有可打印报表均由两部分组成:

  1. ir.actions.report 记录:定义报表名称、关联模型、纸张格式以及需要渲染的模板。
  2. QWeb模板(类型为qweb的ir.ui.view视图):即最终渲染为PDF文件的HTML/XML布局内容。

继承报表时,操作对象是QWeb模板,而非报表动作记录。其实现方式与表单视图、列表视图的继承逻辑一致,均通过inherit_id参数完成配置。

基础继承用法

步骤一:查找待继承的模板

首先确定目标报表模板的外部ID。例如,Odoo标准发票报表模板的外部ID为:account.report_invoice_document。

你可以开启开发者模式,在设置 > 技术 > 报表中查看对应报表获取该ID,也可在对应Odoo模块的源码XML文件中检索查询。

步骤二:在XML文件中创建继承视图

<odoo>
  <template id="custom_invoice_report"
            inherit_id="account.report_invoice_document">
    <!-- 通过XPath定位指定节点 -->
    <xpath expr="//div[@class='page']" position="inside">
      <div class="row">
        <div class="col-12">
          <p>Custom note: <t t-esc="o.custom_field_id.name"/></p>
        </div>
      </div>
    </xpath>
  </template>
</odoo>

建议使用模块名作为模板ID前缀,避免ID冲突,示例:my_module.custom_invoice_report。

XPath 位置属性说明

<xpath>标签中的position属性,用于控制新增内容相对于匹配节点的插入位置:

  • inside:将内容追加至匹配元素内部,作为其最后一级子元素
  • before:在匹配元素的前方插入内容
  • after:在匹配元素的后方插入内容
  • replace:使用自定义内容完全替换原有匹配元素
  • attributes:修改匹配元素的属性值(常用于新增CSS样式类)

示例:添加样式类属性

<xpath expr="//table[@class='table table-sm']"
        position="attributes">
  <attribute name="class">table table-sm table-bordered</attribute>
</xpath>

为销售订单报表添加自定义字段

假设你已在sale.order模型中新增字段delivery_notes,并需要将该字段展示在销售订单打印报表中,完整继承代码如下:

<odoo>
  <template id="sale_order_custom_notes"
            inherit_id="sale.report_saleorder_document">
    <!-- 在订单信息表格后方插入内容 -->
    <xpath expr="//p[@name='payment_term']" position="after">
      <t t-if="doc.delivery_notes">
        <div class="row mt-3">
          <div class="col-12">
            <strong>Delivery Notes:</strong>
            <p><t t-esc="doc.delivery_notes"/></p>
          </div>
        </div>
      </t>
    </xpath>
  </template>
</odoo>

代码中使用了t-if条件判断标签,这是推荐的编码规范:当字段无内容时自动隐藏对应区块,保证打印页面整洁美观。

继承子模板(t-call 调用模板)

Odoo的多数报表由多个子模板组合而成,通过<t t-call="..."/>标签进行调用。例如发票报表会分别调用通用地址模块、明细表格、税额汇总等独立子模板。

你可以直接使用子模板的外部ID作为inherit_id,对其单独继承修改。这种方式比直接继承顶层文档模板更加精准、灵活。

示例:继承发票税额汇总子模板

<!-- 继承发票税额汇总子模板 -->
<template id="custom_invoice_tax_totals"
          inherit_id="account.document_tax_totals">
  <xpath expr="//t[@t-foreach]" position="after">
    <tr>
      <td colspan="2">
        <em>All prices include applicable duties.</em>
      </td>
    </tr>
  </xpath>
</template>

Odoo 19 依旧支持report.layout全局布局机制。若需要统一修改所有报表的样式(如全局页眉、页脚品牌信息),可继承web.report_layout模板。

配置清单文件 manifest.py

务必在模块的__manifest__.py中声明上述XML文件:

'data': [
    'views/report_templates.xml',
],

报表模板文件需配置在data节点下,不可放入assets。若报表需要自定义CSS样式,CSS文件单独配置在assets节点,模板XML文件始终归类至data。

总结

Odoo 19 的报表继承逻辑与视图继承保持一致:查找模板外部ID、编写XPath定位节点、设置内容插入位置即可完成定制。

该方式能将所有定制内容隔离在自定义模块中,相比直接复制修改系统原生模板,大幅降低版本升级与后期维护的难度。

无论是新增自定义字段、调整页面布局,还是设置条件展示区块,基于XPath的继承方式都能实现精细化控制,同时规避直接修改核心代码带来的各类风险。

Odoo 19 报表继承开发手册
中国 Odoo, 苏州远鼎 2026年6月12日
标签
存档