生成 PDF 報告?
重要
本教程是 開始 教程的擴展。請確保您已經完成了該教程,并使用您構建的 estate
模塊作為本教程中練習的基礎。如果您想從一個干凈的基礎開始,請從 technical-training-solutions 存儲庫中獲取 16.0-core
分支。
之前我們已經 介紹了QWeb ,并且使用它來構建看板視圖?,F在我們將擴展QWeb的另一個主要用途:創建PDF報告。常見的業務需求是能夠創建文檔以發送給客戶并在內部使用。這些報告可以用來總結和展示信息,以有組織的模板支持業務的不同方面。Odoo還可以在最小的額外工作下添加我們公司的頁眉和頁腳到我們的報告中。
有關此主題的文檔可以在 QWeb模板 , QWeb報告 和 Actions 參考文獻的 報告操作 ( ir.actions.report ) 部分找到。
文件結構?
PDF報告的主要部分是其QWeb模板。通常還需要相應的 ir.actions.report
,將報告包含在模塊的業務邏輯中。文件名或位置沒有嚴格的規定,但這兩個部分通常存儲在模塊目錄頂層的 report
文件夾中的2個單獨文件中。如果一個模塊有許多或多個長報告模板,則通常會在不同的文件中邏輯地組織它們,這些文件以它們包含的報告命名。所有報告的操作通常存儲在同一個文件中,該文件以 _reports.xml
結尾,無論它包含多少個報告。
因此,您的工作目錄應該看起來像這樣:
estate
├── models
│ ├── *.py
│ └── __init__.py
├── report
│ ├── estate_property_templates.xml
│ └── estate_property_reports.xml
├── security
│ └── ir.model.access.csv
├── views
│ └── *.xml
├── __init__.py
└── __manifest__.py
請注意,您在報表文件夾中經常會看到其他非QWeb和非XML文件也包含“report”在它們的名稱中。這些與本教程中涵蓋的報表無關,而是在 在儀表板中可視化數據 教程中介紹?,F在,您可以將它們視為使用直接SQL查詢(有時稱為SQL視圖)的自定義視圖。
不要忘記將模板和操作視圖所需的任何文件添加到您的 __manifest__.py
中。在這種情況下,您需要將文件添加到 data
列表中,并記住清單中列出的文件是按順序加載的!
基本報告?
注解
目標 : 在本節結束時,我們將能夠打印一份報告,顯示某個物業的所有報價。

在我們的房地產示例中,我們可以創建許多有用的報告。我們可以創建一個簡單的報告,顯示所有房產的報價。
報告數據?
在我們開始之前,我們首先需要一些數據來填充我們的報告,否則這個教程將會很無聊。在創建報告時,您需要一些數據來測試您的報告代碼,并檢查結果的外觀是否符合預期。最好使用能夠涵蓋大部分或所有預期用例的數據進行測試。我們簡單報告的一個良好的代表性集合是:
至少有3個屬性,其中1個是”已售出”,1個是”已收到報價”,1個是”新的”。
我們的“已售出”和“已收到報價”的房產至少需要2-3個報價
如果你還沒有這樣的數據集,你可以選擇:
完成 定義模塊數據 教程(如果您還沒有完成),并將額外的案例添加到您的演示數據中(您可能需要創建一個新的數據庫來加載演示數據)。
在數據庫中手動創建數據。
將此 數據文件 復制到您的 estate 模塊的新目錄(data)中,并將 這些行 復制到您的 __manifest__.py 文件中(您可能需要創建一個新的數據庫來加載演示數據)。
在繼續之前,請瀏覽您數據庫中的數據,并確保您的數據符合預期。當然,您可以在編寫報告代碼后添加數據,但這樣您將無法逐步測試編寫代碼的部分。對于復雜的報告,在長期運行中,這可能會使檢查錯誤和調試代碼更加困難。
最小模板?
在 報告模板 文檔的 “Minimal viable template” 部分中,可以查看一個最小可行模板。我們可以修改此示例以構建我們的最小房產報價模板文件:
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="report_property_offers">
<t t-foreach="docs" t-as="property">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<h2>
<span t-field="property.name"/>
</h2>
<div>
<strong>Expected Price: </strong>
<span t-field="property.expected_price"/>
</div>
<table class="table">
<thead>
<tr>
<th>Price</th>
</tr>
</thead>
<tbody>
<t t-set="offers" t-value="property.mapped('offer_ids')"/>
<tr t-foreach="offers" t-as="offer">
<td>
<span t-field="offer.price"/>
</td>
</tr>
</tbody>
</table>
</div>
</t>
</t>
</t>
</template>
</odoo>
我們文件中的大部分Odoo特定(即非HTML)項目在最小可行模板部分中有解釋。我們模板中的一些其他功能包括:
使用
class="table"
屬性,使我們的表格具有一些漂亮的格式。您可以在報告模板中使用 Twitter Bootstrap(在本例中我們使用了它的表格類)和 Font Awesome(用于添加圖標)類。使用
t-set
、t-value
、t-foreach
和t-as
,以便我們可以循環遍歷所有的offer_ids
。
如果您已經熟悉了網站模板引擎,那么 QWeb 指令(即 t-
命令)可能不需要太多解釋,您可以直接查看其 文檔 并跳過到下一小節。
否則,您可以閱讀更多關于它們的信息( Wikipedia 提供了很好的高級描述),但總體思路是QWeb提供了根據Odoo數據和簡單命令動態生成Web代碼的能力。也就是說,QWeb可以訪問記錄集數據(和方法)并處理設置和訪問臨時變量等簡單編程操作。例如,在上面的示例中:
t-set
創建一個名為 “offers” 的臨時變量,其值由t-value
設置為當前estate.property
記錄集的offer_ids
。t-foreach
和t-as
的使用相當于 Python 中的:
for offer in offers:
報表操作?
現在我們有了一個模板,需要通過 ir.actions.report
使其在我們的應用程序中可訪問。 ir.actions.report
的一個實際示例在 這里 對應于 `這個模板<https://github.com/odoo/odoo/blob/0e12fa135882cd5095dbf15fe2f64231c6a84336/addons/event/report/event_event_templates.xml#L5>`__。 其內容在 文檔 中都有解釋。
ir.actions.report
主要通過模型視圖的打印菜單使用。在實際示例中, binding_model_id
指定了報表應該顯示哪個模型的視圖,Odoo 會自動為您添加。報表操作的另一個常見用例是將其鏈接到按鈕,就像我們在 第十章:準備好行動了嗎? 中學到的那樣。這對于只在特定條件下有意義的報表非常方便。例如,如果我們想制作一個“最終銷售”報表,那么我們可以將其鏈接到“打印銷售信息”按鈕,該按鈕僅在屬性為“已售出”時在表單視圖中顯示。

你可能已經注意到或者想知道為什么我們的報告模板要循環遍歷記錄集。當我們的模板傳遞多個記錄時,它可以為所有記錄生成一個PDF報告。在列表視圖中選擇多個記錄并使用打印菜單可以演示這一點。
生成報告?
最后,您現在知道在哪里創建文件以及文件內容應該如何。祝您制作報告愉快!
Exercise
生成報告。
將最小模板子部分的房產報告屬性添加到房產視圖的打印菜單中。
通過添加更多數據來改進報告。請參考本節的 目標 ,了解可以添加哪些附加數據,并隨意添加更多內容。
獎勵:通過添加一些邏輯,使報告更加靈活,當某個屬性上沒有報價時,我們不創建表格,而是寫一些關于還沒有報價的內容。提示:您需要使用“t-if”和“t-else”。
請記得檢查您的PDF報告是否符合預期的數據。
子模板?
注解
目標 :本節結束時,我們將擁有一個子模板,可在兩個報告中使用。

使用子模板有兩個主要原因。一是在處理特別長或復雜的模板時,使代碼更易于閱讀。另一個原因是盡可能地重用代碼。我們的簡單物業報告很有用,但列出物業報價信息可以用于不止一個報告模板。一個例子是列出一個銷售員所有物業報價的報告。
通過閱讀 文檔 或查看 示例,了解如何調用子模板(請記住,無論是報表還是Odoo中的視圖,QWeb都使用相同的控制流程)。
Exercise
創建并使用子模板。
將報價單的表格部分拆分到單獨的模板中。記得在此之后檢查原始報告是否仍然可以正確打印。
為
res.users
添加一個新報告,允許您打印在其表單視圖中可見的所有房地產屬性(即在“設置”應用程序中)。在同一報告中包括每個銷售員的房產的報價。提示:由于此情況下的binding_model_id
不在房地產模塊中,因此您需要使用ref="base.model_res_users"
。您的最終結果應該與本節的 目標 中的圖像類似。
請記得檢查您的報表是否符合預期的數據!
報告繼承?
注解
目標 : 在本節結束時,我們將繼承 estate_account
模塊中的財產報告。

QWeb中的繼承使用與 視圖繼承 相同的 xpath
元素。但是,QWeb模板引用其父模板的方式不同。只需將 inherit_id
屬性添加到 template
元素中,并將其設置為 module.parent_template_id 即可更容易地實現。
我們沒有向 estate_account
中的任何房地產模型添加新字段,但我們仍然可以向現有的財產報告中添加信息。例如,我們知道任何“已售出”的房產都已經為其創建了發票,因此我們可以將此信息添加到我們的報告中。
Exercise
繼承一個報告。
擴展財產報告,包括一些關于發票的信息。您可以查看本節的 目標 以獲取靈感(即在財產完成時打印一行,否則不打印任何內容)。
再次提醒,記得檢查報告與數據是否符合預期!
附加功能?
所有下列額外功能在 QWeb報告 文檔中有詳細描述,包括如何實現每一個功能。
翻譯?
我們都知道Odoo可以通過自動化和手動翻譯來支持多種語言。QWeb報告也不例外!請注意,如果模板的文本內容中存在不必要的空格,尤其是前導空格,有時翻譯可能無法正常工作,請盡可能避免它們。
報告是網頁?
你可能已經聽膩了QWeb創建HTML的說法,但我們還是要再說一遍!使用QWeb編寫報告的一個很棒的特性是它們可以在Web瀏覽器中查看。如果您想嵌入一個超鏈接,以便導航到特定的報告,這將非常有用。請注意,通常的安全檢查仍將適用,以防止未經授權的用戶訪問報告。
條形碼?
Odoo內置了條形碼圖像創建器,允許在您的報表中嵌入條形碼。查看相應的 代碼 以查看所有支持的條形碼類型。