相关文章推荐
鼻子大的日记本  ·  How to receive ...·  7 月前    · 
憨厚的佛珠  ·  expecting ...·  1 年前    · 
文武双全的松鼠  ·  How can men reduce ...·  1 年前    · 
旅途中的鼠标垫  ·  Get walk-in testing ...·  1 年前    · 

Odoo 13开发者文档:QWeb报表

Odoo Alan 4年前 (2020-01-21) 10204次浏览 2个评论 扫描二维码
本文来自 Odoo 13官方文档之开发者文档 系列文章
以HTML/QWeb像在Odoo中其它普通视图那样编写报表。 你可以使用通常的 QWeb控制流工作 。PDF渲染本身由 wkhtmltopdf 执行。如果你想要对某个模型创建报表,会需要定义这个 报表 及其需要使用的 报表模板 。 如果你想要,也可以为报表指定一个特定的 纸张格式 。最终,如果需要访问自己的模型之外的内容,可以定义一个给予你访问更多模型及模板中记录的权限的 自定义报表 类。

每个报表必须由 报表动作 声明。

为进行简化, <report> 元素快捷方式在定义报表可以使用, 而非需要手动设置 动作 及其周边内容。这个 <report> 可以接收如下属性:

所生成记录的 外部id
name (必填)
仅在某种列表中查找内容时用于报表的助记内容/描述
model (必填)
你的报表会相关的模型
report_type (必填)
PDF报表的 qweb-pdf 或HTML的 qweb-html
report_name
你的报表名称(将会是PDF的输出名)
groups
允许浏览/使用当前报表的组的 Many2many 字段
attachment_use
若设置为True, 使用 attachment 表达式所生成的名称存储为附件的报表;如果需要仅生成一次报表可以使用它 (例如出于法律原因)
attachment
定义报表名称的python 表达式;记录可作为 object 变量访问
paperformat
希望使用的纸张格式的外部id(如未指定默认为公司的纸张格式)
file="account.report_invoice" attachment_use="True" attachment="(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/','')+'.pdf')"
1
2
3
4
5
6
7
8
9
10
11
< report
id = "account_invoices"
model = "account.invoice"
string = "Invoices"
report_type = "qweb-pdf"
name = "account.report_invoice"
file = "account.report_invoice"
attachment_use = "True"
attachment = "(object.state in ('open','paid')) and
('INV'+(object.number or '').replace('/','')+'.pdf')"
/ >
1
2
3
4
5
6
7
8
9
10
11
12
< template id = "report_invoice" >
< t t - call = "web.html_container" >
< t t - foreach = "docs" t - as = "o" >
< t t - call = "web.external_layout" >
< div class = "page" >
< h2 > Report title < / h2 >
< p > This object ' s name is < span t - field = "o.name" / > < / p >
< / div >
< / t >
< / t >
< / t >
< / template >

调用 external_layout 会在报表上添加头部和底部。PDF内容体是 <div class="page"> 内部的内容。 模板的 id 必须为在报表声明中指定的名称;例如对上面的报表为 account.report_invoice 。因为这是一个QWeb模板,你可以访问由模板接收的 docs 对象的所有字段。

有一些可在报表中访问的具体变量,主要有:

针对当前报表的记录
doc_ids
针对 docs 记录的id列表
doc_model
针对 docs 记录的模型
对Python标准库 time 的引用
打印报表的用户的 res.user 记录
res_company
当前 user 的公司的记录

如果你希望访问模板中的记录/模型的其它记录,会需要用到 自定义报表

如果要翻译报表 (如翻译到伙伴的语言),需要定义两个模板:

  • 主报表模板
  • 可翻译的文档
  • 然后可以调用通过将属性设置 t-lang 为语言代码(例如 fr en_US )或是记录字段的主模板中的可翻译文档。如果使用可翻译的字段(如国家名、销售条件等)还需要通过相应的上下文重新浏览相关记录。

    如果报表模板不使用可翻译记录字段,不需要在另一种语言中重新浏览记录且这样会影响性能。

    例如,我们来看一下Sale模块中的销售订单报表:

    <t t-call="web.html_container"> <t t-foreach="docs" t-as="doc"> <t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/> </template> <!-- Translatable template --> <template id="report_saleorder_document"> <!-- Re-browse of the record with the partner lang --> <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" /> <t t-call="web.external_layout"> <div class="page"> <div class="oe_structure"/> <div class="row"> <div class="col-6"> <strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoice and shipping address:</strong> <strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoice address:</strong> <div t-field="doc.partner_invoice_id" t-options="{&quot;no_marker&quot;: True}"/> <div class="oe_structure"/> </template>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    < ! -- Main template -- >
    < template id = "report_saleorder" >
    < t t - call = "web.html_container" >
    < t t - foreach = "docs" t - as = "doc" >
    < t t - call = "sale.report_saleorder_document" t - lang = "doc.partner_id.lang" / >
    < / t >
    < / t >
    < / template >
    < ! -- Translatable template -- >
    < template id = "report_saleorder_document" >
    < ! -- Re - browse of the record with the partner lang -- >
    < t t - set = "doc" t - value = "doc.with_context(lang=doc.partner_id.lang)" / >
    < t t - call = "web.external_layout" >
    < div class = "page" >
    < div class = "oe_structure" / >
    < div class = "row" >
    < div class = "col-6" >
    < strong t - if = "doc.partner_shipping_id == doc.partner_invoice_id" > Invoice and shipping address : < / strong >
    < strong t - if = "doc.partner_shipping_id != doc.partner_invoice_id" > Invoice address : < / strong >
    < div t - field = "doc.partner_invoice_id" t - options = "{&quot;no_marker&quot;: True}" / >
    < . . . >
    < div class = "oe_structure" / >
    < / div >
    < / t >
    < / template >
    margin_top , margin_bottom , margin_left , margin_right
    单位为mm的边框大小
    page_height , page_width
    单位为mm的页面大小
    orientation
    横向或纵向
    header_line
    显示头部线的布尔值
    header_spacing
    单位为mm的头部间距
    <record id="paperformat_frenchcheck" model="report.paperformat"> <field name="name">French Bank Check</field> <field name="default" eval="True"/> <field name="format">custom</field> <field name="page_height">80</field> <field name="page_width">175</field> <field name="orientation">Portrait</field> <field name="margin_top">3</field> <field name="margin_bottom">3</field> <field name="margin_left">3</field> <field name="margin_right">3</field> <field name="header_line" eval="False"/> <field name="header_spacing">3</field> <field name="dpi">80</field> </record>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    < record id = "paperformat_frenchcheck" model = "report.paperformat" >
    < field name = "name" > French Bank Check < / field >
    < field name = "default" eval = "True" / >
    < field name = "format" > custom < / field >
    < field name = "page_height" > 80 < / field >
    < field name = "page_width" > 175 < / field >
    < field name = "orientation" > Portrait < / field >
    < field name = "margin_top" > 3 < / field >
    < field name = "margin_bottom" > 3 < / field >
    < field name = "margin_left" > 3 < / field >
    < field name = "margin_right" > 3 < / field >
    < field name = "header_line" eval = "False" / >
    < field name = "header_spacing" > 3 < / field >
    < field name = "dpi" > 80 < / field >
    < / record >
    @api.model def _get_report_values(self, docids, data=None): report_obj = self.env['ir.actions.report'] report = report_obj._get_report_from_name('module.report_name') docargs = { 'doc_ids': docids, 'doc_model': report.model, 'docs': self, return docargs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from odoo import api , models
    class ParticularReport ( models . AbstractModel ) :
    _name = 'report.module.report_name'
    @ api . model
    def _get_report_values ( self , docids , data = None ) :
    report_obj = self . env [ 'ir.actions.report' ]
    report = report_obj . _get_report_from_name ( 'module.report_name' )
    docargs = {
    'doc_ids' : docids ,
    'doc_model' : report . model ,
    'docs' : self ,
    }
    return docargs

    If you want to use如果希望使用自定义字段则需要向 web.reports_assets_common 资源包添加自定义字体相相关联的 less/CSS。向 web.assets_common web.assets_backend 添加自定义字体不会让该字体在QWeb可用。

    <template id="report_assets_common_custom_fonts" name="Custom QWeb fonts" inherit_id="web.report_assets_common"> <xpath expr="." position="inside"> <link href="/your_module/static/src/less/fonts.less" rel="stylesheet" type="text/less"/> </xpath> </template> @font-face { font-family: 'MonixBold'; src: local('MonixBold'), local('MonixBold'), url(/your_module/static/src/fonts/MonixBold-Regular.otf) format('opentype'); .h1-title-big { font-family: MonixBold; font-size: 60px; color: #3399cc;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @ font - face {
    font - family : 'MonixBold' ;
    src : local ( 'MonixBold' ) , local ( 'MonixBold' ) , url ( / your_module / static / src / fonts / MonixBold - Regular . otf ) format ( 'opentype' ) ;
    }
    . h1 - title - big {
    font - family : MonixBold ;
    font - size : 60px ;
    color : #3399cc;
    }