Odoo 12開發之報表和服務端 QWeb


Odoo 12開發之報表和服務端 QWeb

前言

Odoo內置的QWeb引擎是報表的默認引擎.
使用 QWeb 模板設計的報表可生成 HTML 文件並被轉化成 PDF

一·安裝wkhtmltopdf模塊

odoo 利用 whktmltopdf 將渲染的HTML頁面轉換成PDF文檔

# 版本依賴參考 https://github.com/wkhtmltopdf/wkhtmltopdf/releases

# 安裝步驟:
	# 1.檢查安裝版本
    	wkhtmltopdf --version
    # 2.卸載不符合的版本
    	sudo apt-get remove --purge wkhtmltopdf
    # 3.下載wkhtmltopdf    
		wget "https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.bionic_amd64.deb" -O /tmp/wkhtml.deb
    # 4. 安裝
    	sudo dpkg -i /tmp/wkhtml.deb
    # 5. 解決缺少依賴
    	sudo apt-get -f install
    # 6. 再次檢查版本信息
    	$ wkhtmltopdf --version
		wkhtmltopdf 0.12.5 (with patched qt)

二·創建業務報表

報表模樣:

Odoo 12開發之報表和服務端 QWeb

### 模塊中報表代碼
# 1. 在當前模塊的根目錄下創建reports文件夾,
#  2. 在reports文件夾下創建library_book_report.xml數據文件
    <?xml version="1.0"?>
    <odoo>
        <report id="action_library_book_report"
                string="Library Books"
                model="library.book"
                report_type="qweb-pdf"
                name="library_app.report_library_book_template" />
    </odoo>	
# 3. 將library_book_report.xml 數據文件加載到 __manifest__.py文件的data下

# 4. 查看當前報表 Settings > Technical > Actions >Reports
### 注意:
	report 標簽表示是一個報表

三·QWeb 報表模板

### 報表遵循一個基本框架
<template id="report_library_book_template">
    <t t-call="web.html_container">
        <t t-call="web.external_layout">
            <div class="page">
                <!-- Report header content -->
                <t t-foreach="docs" t-as="o">
                    <!-- Report row content -->
                </t>
                <!-- Report footer content -->
            </div>
        </t>
    </t>
</template>
# 1. 最重要的元素是 t-call 標准報表結構
# 2. web.html_container模板進行支持HTML文檔的基本設置
# 3. web.external_layout模板使用相應公司的相關設置處理報表頭部和底部

四·在報表中展示數據

# 報表中QWeb模板在服務端進行渲染. 使用Python QWeb來實現.
# 注意區別
    # QWeb表達式是有python語法運行,不是JavaScript. 
    # 對於簡單的表達式沒有區別,對於復雜的預算則可能存在差別.
    ### 表達式的上下文不同,其中報表可使用的變量:
    	# docs  打印記錄的可迭代集合
    	# doc_ids 打進記錄的ID列表
    	# doc_model 指定記錄的模型.
    	# time 是對python時間庫的引用
    	# user 是運行報表的用戶記錄
    	# res_company 是當前用戶的公司記錄
        
### odoo報表采用bootstrap樣式       
#### 添加表格表頭
<!-- Report header content -->
<div class="container">
    <!-- 表頭 header一欄  -->
    <div class="row bg-primary">
        <div class="col-3">Title</div>
        <div class="col-2">Publisher</div>
        <div class="col-2">Date</div>
        <div class="col-3">Publisher Address</div>
        <div class="col-2">Authors</div>
    </div>
    <t t-foreach="docs" t-as="o">
        <div class="row">
            <!-- Report row content -->
        </div>
    </t>
    <!-- Report footer content -->
</div>
### 循環數據 , 在 t-foreach 標簽取出數據
	# docs指定可迭代的集合 t-as 作為別名
	# t-options屬性添加額外的選項,widget鍵的json字典. 有時候需要渲染出地址,默認widget為contact,類似與地圖圖標

<!-- Report row content -->
<div class="col-3">
    <h4><span t-field="o.name" /></h4>
</div>
<div class="col-2">
    <span t-field="o.publisher_id" />
</div>
<div class="col-2">
    
    <span t-field="o.date_published"
          t-options="{'widget': 'date'}"/> 
</div>
<div class="col-3">
    <span t-field="o.publisher_id"
          t-options='{
                     "widget": "contact",
                     "fields": ["address", "email", "phone", "website"],
                     "no_marker": true}'/>
</div>
<div class="col-2">
    <!-- Render authors -->
</div>

五·渲染圖片

# 渲染作者頭像圖片 t-options的widget為image
<!-- Render authors -->
<ul class="list-unstyled">
    <t t-foreach="o.author_ids" t-as="author">
        <li class="media">
            <span t-field="author.image_small"
                t-options="{'widget': 'image'}" />
            <div class="media-body">
                <p class="mt-0">
                    <span t-field="author.name" />
                </p>
            </div>
        </li>
    </t>
</ul>

六·報表匯總

# 報表中需要進行匯總 ,借助python表達式來計算集合元素的數量. 可以使用sum函數,以及推導式
# 在 <t t-foreach>標簽閉合后,添加最后一行用於匯總

# t-esc  執行python表達式   t-set 定義累加變量,  t-value 可以設置值(python表達式和t-set變量進行計算)
<!-- Report footer content -->
<div class="row">
    <div class="col-3">
        Count: <t t-esc="len(docs)" />
    </div>
    <div class="col-2" />
    <div class="col-2" />
    <div class="col-3" />
    <div class="col-2" />
</div>

七·定義紙張樣式

# 自定義紙張的樣式 在報表xml數據最上方添加如下代碼
# 查看 Settings > Technical > Reporting > Paper Format菜單
# 在 report 標簽屬性種,paperfomat屬性可以用來實現編輯報表的操作
<record id="paperformat_euro_landscape"
        model="report.paperformat">
    <field name="name">European A4 Landscape</field>
    <field name="default" eval="True" />
    <field name="format">A4</field>
    <field name="page_height">0</field>
    <field name="page_width">0</field>
    <field name="orientation">Landscape</field>
    <field name="margin_top">40</field>
    <field name="margin_bottom">23</field>
    <field name="margin_left">7</field>
    <field name="margin_right">7</field>
    <field name="header_line" eval="False" />
    <field name="header_spacing">35</field>
    <field name="dpi">90</field>
</record>

八·在報表中啟用語言翻譯

# 在報表種啟用翻譯時, 需要使用 t-lang屬性的 <t t-call>元素在模板中調用翻譯方法.
# t-lang傳入語言代碼來運行,如es,en_US.
<report id="action_library_book_report"
        ...
        name="library_app.report_library_book_translated"
        paperformat="paperformat_euro_landscape" />

<template id="report_library_book_template">
    <t t-call="library_app.report_library_book_translated"
       t-lang="user.lang" />
</template>
####### 有些情況下,我們可能需要每條記錄以指定語言進行渲染。比如在銷售訂單中,我們可能要各條記錄按照對應合作方/客戶的首選語言進行打印。假設我們需要每本書按照對應出版商的語言進行渲染,QWeb模板可以這么寫
<template id="report_library_book_translated">
    <t t-foreach="docs" t-as="o">
        <t t-call="library_app.report_library_book_template"
           t-lang="o.publisher_id.lang">
            <t t-set="docs" t-value="o" />
        </t>
    </t>
</template>

九·使用自定義 SQL 創建報表

# 寫原生 SQL 查詢來創建我們所需的數據集,將結果通過特殊的模型進行暴露,然后基於這一數據集來生成報表
# 目的是:在QWeb模板中不易於處理的數據轉換或累加
###  自定義 報表查詢語句,
# 將 reports 加入到 __init__.py, 和reports的__init__.py
# 在reports/library_book_report.py
from odoo import models, fields

class BookReport(models.Model):
    _name = 'library.book.report'
    _description = 'Book Report'
    _auto = False

    name = fields.Char('Title')
    publisher_id = fields.Many2one('res.partner')
    date_published = fields.Date()

    def init(self):
        self.env.cr.execute("""
            CREATE OR REPLACE VIEW library_book_report AS
            (SELECT *
            FROM library_book
            WHERE active=True)
        """)
        
# 添加安全訪問規則 security/ir.model.access.csv
access_library_book_report,access_library_book_report,model_library_book_report,
library_group_user,1,0,0,0
# 在	reports/library_book_sql_report.xml 新增一個報表
<?xml version="1.0"?>
<odoo>
    <report id="action_library_book_sql_report"
            string="Library Book SQL Report"
            model="library.book.report"
            report_type="qweb-html"
            name="library_app.report_library_book_sql" />

    <template id="report_library_book_sql">
        <t t-call="web.html_container">
            <t t-call="web.external_layout">
                <div class="page">
                    <!-- Report page content -->
                    <table class="table table-striped">
                        <tr>
                            <th>Title</th>
                            <th>Published</th>
                            <th>Date</th>
                        </tr>
                        <t t-foreach="docs" t-as="o">
                            <tr>
                                <td class="col-xs-6">
                                    <span t-field="o.name" />
                                </td>
                                <td class="col-xs-3">
                                    <span t-field="o.publisher_id" />
                                </td>
                                <td class="col-xs-3">
                                    <span t-field="o.date_published"
                                          t-options="{'widget': 'date'}" />
                                </td>
                            </tr>
                        </t>
                    </table>
                </div>
            </t>
        </t>
    </template>
</odoo>
# 在views/library_menu.xml中添加如下內容
<act_window id="action_library_book_report"
            name="Book Report"
            res_model="library.book.report"
            view_mode="tree,form"
            />
<menuitem id="menu_library_book_report"
          name="Book Report"
          parent="menu_library"
          action="action_library_book_report"
          />


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM