# QWeb (Odoo glossary)

Canonical: https://erpfly.com/glossary/qweb/
Last updated: September 14, 2026

**Definition:** QWeb is Odoo's XML templating engine. A QWeb template is ordinary XML or HTML with t- directives such as t-if, t-foreach, t-out and t-call, and Odoo uses it to render PDF reports and website and portal pages on the server and, through OWL, the web client's components in the browser.

Also called: Odoo QWeb, QWeb report, QWeb template

If you've changed what a quotation PDF prints, you've touched QWeb. The same syntax also drives website pages and the whole web client, but two different engines render it, and mixing them up is where most of the confusion starts.

### Two engines, one syntax

On the server, `ir.qweb` renders templates stored as views. Reports go through it, get wrapped in a layout and are turned into PDF by wkhtmltopdf. Website and portal pages use the same Python engine. In the browser, OWL compiles QWeb templates from your addon's static XML files into components.

Most directives work on both sides, but not all. `t-field`, which formats a record field according to its type and can take `t-options` such as a widget, is Python only. `t-name`, `t-inherit` and `t-inherit-mode` are how static JavaScript templates are named and extended.

### The directives that do the work

`t-if`, `t-elif` and `t-else` handle conditions. `t-foreach` with `t-as` loops, and gives you extra variables like `line_index`, `line_first` and `line_last` when you write `t-as="line"`. `t-set` with `t-value` stores a value. `t-call` renders another template, and whatever you put inside the call is available there as `0`. `t-att-href` computes an attribute value, and `t-attf-class` builds one from a format string.

For output, use `t-out`. It escapes HTML unless the value is already marked safe, such as an HTML field or a `markupsafe.Markup`. `t-esc` still works as an alias and the docs haven't formally deprecated it, but they list it under deprecated output directives, so new code should say `t-out`. `t-raw` was deprecated in Odoo 15.

### Adding a line to the quotation PDF

The sale order document, `sale.report_saleorder_document`, has a `div` with `id="informations"` holding the reference and date blocks in 17, 18 and 19. That id makes a steady anchor:

```xml
<template id="report_saleorder_document_delivery_window"
          inherit_id="sale.report_saleorder_document">
    <xpath expr="//div[@id='informations']" position="inside">
        <div t-if="doc.delivery_window" class="col" name="informations_delivery_window">
            <strong>Delivery window</strong>
            <div t-field="doc.delivery_window"/>
        </div>
    </xpath>
</template>
```

`doc` is the variable the sale report sets inside its loop over `docs`. The positions and locators are the ones described under XPath view inheritance. The inner classes around that div changed between 17 and 18, so check the rendered PDF on each version you support.

### Where QWeb work goes wrong

**Copying the whole template.** Duplicating `report_saleorder_document` to change one line means the next Odoo release's fixes never reach your copy. Inherit and xpath instead. That's how erpfly delivers report changes in the addons it generates, and our [Odoo customization](https://erpfly.com/odoo-customization/) page walks through a fuller quotation example.

**Custom report models that lose `docs`.** If you define `report.<module>.<report_name>` with `_get_report_values`, Odoo stops providing `docs`, `doc_ids` and `doc_model` for you. Return them yourself, or any template that loops over `docs` breaks.

**Expecting `t-lang` everywhere.** Translating a report into the partner's language works by putting `t-lang` on a `t-call`. On any other element it won't translate anything.

**Wrapping values in `Markup` to silence escaping.** It tells QWeb the content is safe without checking. For anything a user typed, that's an XSS hole.

If you're coming from ERPNext, the closest counterpart is the Print Format, which uses Jinja rather than XML directives.

See also: https://erpfly.com/glossary/owl/, https://erpfly.com/glossary/xpath-view-inheritance/, https://erpfly.com/glossary/print-format/, https://erpfly.com/glossary/odoo-addon/

### Sources

- [QWeb Templates, Odoo 19 developer documentation](https://www.odoo.com/documentation/19.0/developer/reference/frontend/qweb.html)
- [QWeb Reports, Odoo 19 developer documentation](https://www.odoo.com/documentation/19.0/developer/reference/backend/reports.html)
- [addons/sale/report/ir_actions_report_templates.xml (19.0), odoo/odoo on GitHub](https://github.com/odoo/odoo/blob/19.0/addons/sale/report/ir_actions_report_templates.xml)