When it comes to running a business, you need to be able to create professional reports. Odoo 19 handles this really well using what it calls QWeb templates. If you’re working with Odoo 19 and want to generate PDF reports, the process is actually straightforward. Odoo relies on QWeb templates to decide how the report should look, and once you connect the template with a report action, the system can turn any record like an invoice or a sales order into a ready-to-download PDF. This means you can create reports that match your business style and make them available directly from the Odoo interface.
This blog will walk you through the step-by-step process of creating a custom PDF report in Odoo 19 for the “project.task” model; it includes setting up the report action and the QWeb template.
Step-by-Step Process for Creating a Custom PDF Report in Odoo 19
Module Structure

Here I have created a module named custom_task_report. This is a basic example of the module structure with a report action and report template inside the report directory.
Report Action (XML)
The next step is creating a report action for the custom report. Inside the “report” directory of your module, create an XML file. Let’s name it task_report.xml. This file contains the action that binds the report to the model. The example below shows how the XML file looks.
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="action_project_report" model="ir.actions.report">
<field name="name">Task Report</field>
<field name="model">project.task</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">custom_task_report.task_report_details</field>
<field name="report_file">custom_task_report.task_report_details</field>
<field name="print_report_name">'Task Report - %s' % (object.display_name)</field>
<field name="binding_model_id" ref="project.model_project_task"/>
<field name="binding_type">report</field>
</record>
</odoo>
Here, in this file, we have defined the action using the following fields.
- name - Here we specify the name of the report action. It helps to find the report within the system. We have given the name “Task Report”.
- model - Specify the model to which the report is associated. The report retrieves the data from this model. We have given the model as “project.task”.
- report_type - This specifies the type of report being generated. The available options are:
- qweb-pdf - To generate the report in PDF using Qweb template.
- qweb-html - To generate the report in HTML using Qweb template.
- qweb-text - To generate the report in plain text format using Qweb template.
- report_name - It links the report action to the QWeb template that will be used to generate the output. The report name is given like “module_name.template_id” . In our case “custom_task_report.task_report_details”.
- report_file - The report_file defines the name of the QWeb template file used for the report. This file contains the XML structure for rendering the report. It’s set to "module_name.template_id". In our case “custom_task_report.task_report_details”.
- print_report_name - Specify the name of the printed report file. The name given here will be on the printed PDF.
- binding_model_id - This is a reference to the model associated with the report action, linking it to other objects. Here, it references the project.task model: "project.model_project_task".
- binding_type - This defines how the report is bound to the system.
- report - Binds the report directly to a record of the specified model.
- action - Binds the report to a specific action that is defined.
In this example, we have chosen the binding_type as report.
The action we have defined above will create a new menu under the gear icon of the associated model. In our case Task Report in the project.task model as shown in the screenshot below.

Qweb Template (XML)
Next, we have to define a QWeb template for the report. This defines the structure and layout of the PDF report. This file is to be created in the report directory of our module. In this example, I have created an XML file named “task_report_template.xml".
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="task_report_details">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<div class="oe_structure"/>
<h2>Task Report</h2>
<br></br>
<p>
Name :
<span t-field="o.display_name"/>
</p>
</div>
</t>
</t>
</t>
</template>
</odoo>
In the Qweb template XML file, you'll set up a template that has the exact same name as the report_name you used in the report action. Inside that template, we use a loop with t-foreach to go through all the task records you've selected. This way, we can create separate content for each item on the list. You can include HTML and QWeb expressions to format and display the information as required.
The example template we created will print the PDF report shown in the screenshot below.

Don’t forget to add both files in the __manifest__.py file like given below in the screenshot.

Creating PDF reports in Odoo 19 with QWeb is a simple yet powerful way to present your data in a professional format. By configuring a report action and designing a custom QWeb template, you can build reports that are both structured and visually clear. With this approach, businesses can generate documents that fit their specific needs while keeping everything smoothly integrated into the Odoo environment.
To read more about How to Create a PDF Report in Odoo 18, refer to our blog How to Create a PDF Report in Odoo 18.