報表是業務應用很是有價值的功能,內置的 QWeb 引擎是報表的默認引擎。使用 QWeb 模板設計的報表可生成 HTML 文件並被轉化成 PDF。也就是說咱們能夠很便捷地利用已學習的 QWeb 知識,應用到業務報表中。本文中咱們將爲圖書館應用添加一個報表,複習 QWeb生成報表的關鍵技巧。包括像彙總一類計算、翻譯和紙張樣式打印。html
本文主要內容有:前端
咱們將繼續使用library_app插件模塊進行學習,該模塊在第三章 Odoo 12 開發之建立第一個 Odoo 應用中初次建立,而後在第五章 Odoo 12開發之導入、導出以及模塊數據和第六章 Odoo 12開發之模型 – 結構化應用數據中進行了改進。相關代碼請參見 GitHub 倉庫。本文完成後代碼也請參見GitHub 倉庫。git
要正確地生成報表,應安裝wkhtmltopdf工具的推薦版本,該工具的名稱表示Webkit HTML to PDF。Odoo使用它來將渲染的 HTML 頁面轉化爲 PDF 文檔。有些版本的wkhtmltopdf庫已知存在問題,好比不打印頁面頭部和底部,因此需挑選使用的版本。從Odoo 10開始,官方支持了0.12.5版本,這也是官方推薦的版本。github
小貼士:官方Odoo項目有一個 wiki 頁面,保持了對於wkthtmltopdf使用的信息和推薦。可經過 GitHub 進行查看。web
不幸的是你的主機系統,不管是Debian/Ubuntu或其它系統,所提供的安裝包版本都不太一致。因此咱們應下載和安裝對於當前操做系統和 CPU 類型的推薦版本包。下載連接請見 GitHub。sql
首先應確保系統中所安裝的不是錯誤的版本:數據庫
若是上述命令打印的結果不是咱們須要的版本,應對其進行卸載。在Debian/Ubuntu系統中,使用的命令以下:bootstrap
下一步咱們須要下載適合咱們系統的安裝包並進行安裝。經過GitHub下載連接進行查看。對於0.12.5,最新 Ubuntu 安裝版本是針對Ubuntu 14.04 LTS穩定版,但對其後的Ubuntu系統應該一樣生效。咱們在最近發佈的Ubuntu 64系統中進行安裝,下載命令以下:sublime-text
下一步應進行安裝。安裝本地deb文件並不會自動安裝依賴,所以須要執行第二步來完成安裝:安全
這時可能會顯示缺乏依賴的錯誤,如下命令可解決這一問題:
如今,咱們能夠檢查wkhtmltopdf庫是否正確安裝並確認是否爲所需版本:
此時Odoo服務的啓動日誌就不會再提示You need Wkhtmltopdf to print a pdf version of the report的信息了。
咱們會繼續使用前面文章所使用的library_app模塊,進添加實現報表的文件。咱們將建立的報表會長成這樣
報表文件應放在模塊子文件夾/reports中。首先咱們來添加一個reports/library_book_report.xml數據文件,不要忘記在__manifest__.py文件的 data 下導入該文件。先在reports/library_book_report.xml文件中聲明一個新報表:
<report>標籤是對向ir.actions.report.xml寫入數據的簡寫形式,這個模型是客戶操做的特殊類型。它的數據可經過Settings > Technical > Actions >Reports菜單進行查看。
小貼士:在設計報表時,咱們可能更傾向保留爲report_type=」qweb-html」而後在完成時再修改成qweb-pdf文件。這樣在QWeb模板中可更快速的生成報表而且更易於檢查 HTML 結果。
執行完模塊升級(~/odoo-dev/odoo/-bin -d dev12 -u library_app)後,圖書表單視圖中會在頂部顯示一個 Print 按鈕(列表視圖中也有),它在Actions按鈕的左側,其中包含添加的運行報表的選項(Library Books)。
如今還沒法生成報表,由於咱們尚未進行定義。這是一個QWeb報表,所以須要用到QWeb模板。name 屬性標識所使用的模板。與其它標識符引用不一樣,name 屬性中須要添加模塊前綴,咱們必須使用完整的引用名稱<module_name>.<identifier_name>。
在下面的代碼能夠看出,這個報表遵循一個基本框架。僅需在reports/library_book_report.xml文件<report>元素後添加以下代碼:
這裏最重要的元素是使用標準報表結構的t-call指令。web.html_container模板進行支持 HTML 文檔的基本設置。web.external_layout模板使用相應公司的相關設置處理報表頭部和底部。可將其替換爲web.internal_layout模板,它將只使用一個基本的頭部。
ℹ️ Odoo 11中的修改
對報表的支持佈局從report 模塊移到了 web 模塊中。也就是說此前版本中使用report.external_layout或report.internal_layout的引用 ,在11.0中引用應修改成web.<…>。
external_layout模板可由用戶自定義,Odoo 11引入了這一選項,在Settings > General Settings菜單中,而後相關內容在Business Documents > Document Template版塊:
這裏咱們能夠點擊Change Document Template來從幾個可用的模板中選取,甚至是點擊Edit Layout來自定義所選模板的 XML。這一個報表框架適用於列表式報表,即報表中每條記錄顯示爲一行。報表頭部一般顯示標題,底部區域則顯示彙總。
另外一種格式是文檔報表,每條記錄是單獨一頁,好比郵件。這種狀況報表結構以下:
咱們會建立一個列表式報表,因此還會使用此前的框架。如今咱們已經有了基本框架。既然報表是QWeb模板,那麼它也能夠像其它視圖那樣進行繼承。報表中使用的QWeb模板可以使用常規視圖繼承使用的 XPath 表達式來進行繼承。
補充:此時點擊打印會輸出一個空白的 PDF 文件。
與看板視圖不一樣,報表中的QWeb模板在服務端進行渲染,所以使用Python QWeb來實現。咱們能夠將其看做相同規格的兩種實現,須要注意其中的一些區別。
首先這裏的QWeb表達式由 Python 語法運行,而非JavaScript。對於最簡的表達式幾乎沒有區別,但更爲複雜的運算則可能存在差異。表達式運行上下文也不一樣,對於報表可以使用以下變量:
可以使用t-field來引用字段值,並可以使用t-options來進行補充指定渲染字段內容的具體組件。
ℹ️Odoo 11中的修改
在此前的 Odoo 版本中,使用的是t-field-options屬性,但在 Odoo 11中淘汰了該屬性,改用t-options屬性。
例如,假設doc表示一條具體記錄,代碼以下:
如今咱們能夠開始設計報表的頁面內容了。
小貼士:不幸的是官方文檔中並無涉及QWeb支持的組件及其選項。因此當前對其作進一步的瞭解只能是經過閱讀相應源碼。可訪問ir_qweb_fields.py,查找繼承ir.qweb.field的類,get_available_options() 方法可有助瞭解支持的選項。
報表內容由HTML書寫,而且使用了Twitter Bootstrap 4來幫助設計報表佈局。在網頁開發中大量使用了Bootstrap,有關Bootstrap的完整指南請見官方網站。
如下爲渲染報表頭部的 XML 代碼,應放在<div class=」page」>中並替換掉現有的<t t-foreach=…>元素:
內容的佈局使用了Twitter Bootstrap的HTML網格系統。總的來講Bootstrap使用12列的網格佈局,此處網格在<div class=」container」>元素中。
ℹ️Odoo 12中的修改
如今Odoo使用Bootstrap 4,它對此前 Odoo 版本中使用的Bootstrap 3並無保持向後兼容。對於從Bootstrap 3改成Bootstrap 4的小技巧,可參照 Odoo 中關於這一話題的 Wiki 頁面。
小貼士:Bootstrap 4 在其大部分構件中使用了 CSS 彈性盒子佈局,已知wkhtmltopdf 對彈性盒子的功能並不都能很好的支持。所以若是有些地方效果不對,請嘗試使用其它元素或方法,如 HTML 表格。
此處咱們爲頭部行添加了標題,而後t-foreach循環遍歷每條記錄並在各行中進行渲染。由於渲染由服務端完成,記錄都是對象,咱們可以使用點號標記來從關聯數據記錄中訪問字段。這也讓關聯字段的數據訪問變得更爲容易。注意這在客戶端渲染的QWeb視圖中是沒法使用的,好比網頁客戶端的看板視圖。
如下是在<div class=」row」>元素中的記錄行內容XML:
能夠看到字段可經過t-options屬性添加額外的選項,內容爲包含帶有widget鍵的 JSON 字典。更爲複雜的示例是contact組件,用於格式化地址。咱們使用它來渲染出版商地址o.publisher_id。默認contact 組件顯示地址時帶有圖像,相似電話圖標。no_marker=」true」選項禁用了這一顯示。
補充:no_marker=」true」禁用的地址圖標如上所示
咱們報表最後一列爲一組帶有頭像的做者。咱們將經過遍從來渲染出每一個做者,並使用Bootstrap媒體對象:
此處咱們遍歷了author_ids,使用字段圖像組件<t t-field=」…」 t-options=」{‘widget’: ‘image’}」>對每一個做者的頭像進行了渲染,而後還有姓名。
注:以上頭像來自各位大神 Twitter 的真實頭像
報表中常常須要提供彙總。這可藉由 Python 表達式來計算總額。在<t t-foreach>閉合標籤以後,咱們添加最後一行用於彙總:
len() Python函數用於計算集合元素的數量。相似地,彙總也可使用sum()來對一組值進行求和運算。例如,可以使用以下列表推導式來進行總額運算:
能夠把這個列表推導式看做一個內嵌的循環。有時咱們須要貫穿報表執行一些計算,如流動彙總(running total),彙總至當前記錄。這可經過t-set 來定義累加變量在每一行進行更新來實現。爲描述這一功能,咱們來計算做者數的累加。首先在docs 記錄集 t-foreach 循環前初始化變量:
而後在循環內,將記錄的做者數添加到變量中。咱們這裏顯示在書名以後,並在每行打印出當前總數:
到這裏咱們的報表的 HTML 顯示沒有問題了,但在打印的 PDF 頁面中還不夠美觀。使用橫向頁面顯示結果會更好,所以下面就來添加紙張樣式。在報表 XML 文件的最上方添加以下代碼:
這是對European A4格式的一個拷貝,這在data/report_paperformat_data.xml文件中定義的base 模塊中,但這裏將排列方向由縱向改成了橫向。定義的紙張樣式可經過後臺Settings > Technical > Reporting > Paper Format菜單進行查看。
如今就可在報表中使用它了。默認的紙張樣式在公司設置中定義,但咱們也能夠爲特定報表指定紙張樣式。這經過在報表操做中的paperfomat屬性來實現。下面來編輯打開報表使用的操做,添加這一屬性:
要在報表中啓用翻譯,須要使用帶有t-lang屬性的<t t-call>元素在模板中調用翻譯方法。t-lang需傳入一個語言代碼來運行,如es或en_US。它須要能夠找到所需使用語言的字段名。一種方式是使用當前用戶的語言,爲此,咱們定義一個外層翻譯報表來調用要翻譯的報表,使用t-lang屬性來設置語言來源:
本例中,每本書都使用了用戶的語言user_id.lang來進行渲染。
有些狀況下,咱們可能須要每條記錄以指定語言進行渲染。好比在銷售訂單中,咱們可能要各條記錄按照對應合做方/客戶的首選語言進行打印。假設咱們須要每本書按照對應出版商的語言進行渲染,QWeb模板能夠這麼寫:
以上咱們對記錄進行了迭代,而後每條記錄根據記錄上的數據使用相應的語言進行報表模板的調用,本例爲出版商的語言publisher_id.lang。
補充:以上代碼運行時每條記錄都會帶有一個頭部,如需按列表顯示還需將頭部抽象到循環以外
前面咱們所建立的報表都是基於常規記錄集,但在有些狀況下咱們須要執行一些在QWeb模板中不易於處理的數據轉換或累加。一種解決方法是寫原生 SQL 查詢來建立咱們所需的數據集,將結果經過特殊的模型進行暴露,而後基於這一數據集來生成報表。
咱們建立reports/library_book_report.py文件來說解這一狀況,代碼以下:
要加載以上文件,須要在模塊的頂級__init__.py文件中添加from . import reports,並在reports/__init__.py文件中添加from . import library_book_report。
_auto屬性用於阻止數據表的自動建立。咱們在模型的init()方法中添加了替代的 SQL。它會建立數據庫視圖,並提供報表所需數據。以上 SQL 查詢很是簡單,旨在說明咱們爲視圖可使用任意有效的 SQL查詢,如對額外數據執行累加或計算。
咱們還須要聲明模型字段來讓 Odoo 知道如何正確處理每一條記錄中的數據。同時不要忘記爲新模型添加安全訪問規則,不然將沒法使用該模型。下面在security/ir.model.access.csv文件中添加下行:
還應注意這是一個全新的不一樣模型,與圖書模型的訪問規則並不相同。下一步基於該模型咱們可使用reports/library_book_sql_report.xml新增一個報表:
對於更爲複雜的狀況,咱們還會須要用戶輸入參數,這時可使用不一樣的方案:嚮導。爲此咱們應建立一個臨時模型來存儲用戶的報表參數。由於這是由代碼生成的,因此咱們可使用所需的任意邏輯。
強烈推薦學習已有的類似報表來獲取靈感。一個不錯的例子是Leaves菜單選項下的Leaves by Department,相應的臨時模型定義能夠參見addons/hr_holidays/wizard/hr_holidays_summary_employees.py。
補充:原書未對這一部分進行驗證,Alan 下面經過添加菜單項的方式來進行驗證,還有其它方式,歡迎讀者留言討論
首先在views/library_menu.xml文件中添加以下內容:
在__manifest__.py 文件中引入前述的 XML 文件後更新模塊
前面一篇文章中,咱們學習了QWeb以及如何使用它來設計看板視圖。本文中咱們學習了QWeb報表引擎,以及使用QWeb模板語言建立報表最爲重要的一些技術。
下一篇文章中,咱們將繼續使用QWeb,此次是建立網頁。咱們將學習書寫網頁控制器,爲咱們的網頁提供更豐富的功能。
☞☞☞第十三章 Odoo 12開發之建立網站前端功能
本文所學習課題的補充參考材料有: