报表是业务应用很是有价值的功能,内置的 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开发之建立网站前端功能
本文所学习课题的补充参考材料有: