Odoo报表动作源码研究 - xiaohao0576/odoo-doc GitHub Wiki
- 源码文件:
odoo/addons/base/models/ir_actions_report.py
- 搜索关键字:
_name = 'ir.actions.report'
- 点击查看源码
report_type = fields.Selection([
('qweb-html', 'HTML'),
('qweb-pdf', 'PDF'),
('qweb-text', 'Text'),
], required=True, default='qweb-pdf',
点击查看源码
@api.model
def _render(self, report_ref, res_ids, data=None):
report = self._get_report(report_ref)
report_type = report.report_type.lower().replace('-', '_')
render_func = getattr(self, '_render_' + report_type, None)
if not render_func:
return None
return render_func(report_ref, res_ids, data=data)
- 如果报表类型是
qweb-pdf
,这个函数就会调用_render_qweb_pdf
函数,点击查看源码 - 如果报表类型是
qweb-html
,这个函数就会调用_render_qweb_html
函数 - 如果报表类型是
qweb-text
,这个函数就会调用_render_qweb_text
函数
这个函数会调用以下两个重要的函数,第一个函数是_pre_render_qweb_pdf
,用于实际生成一组单页的pdf的内容。
然后再调用_merge_pdfs
函数,把单页的pdf组合成一个pdf文档,并返回二进制pdf内容
这个函数主要是调用_render_qweb_pdf_prepare_streams
- 调用
_render_qweb_html
函数生成html - 调用
_prepare_html
获得bodies, html_ids, header, footer, specific_paperformat_args - 调用
_run_wkhtmltopdf
,把html网页转化为pdf文件
html = self.with_context(**additional_context)._render_qweb_html(report_ref, all_res_ids_wo_stream, data=data)[0]
bodies, html_ids, header, footer, specific_paperformat_args = report_sudo.with_context(**additional_context)._prepare_html(html, report_model=report_sudo.model)
pdf_content = self._run_wkhtmltopdf(
bodies,
report_ref=report_ref,
header=header,
footer=footer,
landscape=self._context.get('landscape'),
specific_paperformat_args=specific_paperformat_args,
set_viewport_size=self._context.get('set_viewport_size'),
)
- 获取页面尺寸定义
- 调用
_build_wkhtmltopdf_args
函数,准备wkhtmltopdf的命令行参数 - 在子进程运行wkhtmltopdf命令
paperformat_id = self._get_report(report_ref).get_paperformat() if report_ref else self.get_paperformat()
# Build the base command args for wkhtmltopdf bin
command_args = self._build_wkhtmltopdf_args(
paperformat_id,
landscape,
specific_paperformat_args=specific_paperformat_args,
set_viewport_size=set_viewport_size)
wkhtmltopdf = [_get_wkhtmltopdf_bin()] + command_args + files_command_args + paths + [pdf_report_path]
process = subprocess.Popen(wkhtmltopdf, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
_out, err = process.communicate()
根据paperformat定义的页面规格,生成wkhtmltopdf需要的命令行参数,点击查看源码
在xml template中调用barcode功能, https://www.odoo.com/documentation/18.0/developer/reference/backend/reports.html#barcodes
点击查看源码
pdf报告也是HTML页面,可以通过网址直接打开HTML页面或者PDF报告
比如: https://mydomain.odoo.com/report/html/sale.report_saleorder_pro_forma/93 https://mydomain.odoo.com/report/html/sale.report_saleorder_pro_forma/93
点击查看源码
@http.route([
'/report/<converter>/<reportname>',
'/report/<converter>/<reportname>/<docids>',
], type='http', auth='user', website=True, readonly=True)
def report_routes(self, reportname, docids=None, converter=None, **data):
report = request.env['ir.actions.report']
context = dict(request.env.context)
if docids:
docids = [int(i) for i in docids.split(',') if i.isdigit()]
if data.get('options'):
data.update(json.loads(data.pop('options')))
if data.get('context'):
data['context'] = json.loads(data['context'])
context.update(data['context'])
if converter == 'html':
html = report.with_context(context)._render_qweb_html(reportname, docids, data=data)[0]
return request.make_response(html)
elif converter == 'pdf':
pdf = report.with_context(context)._render_qweb_pdf(reportname, docids, data=data)[0]
pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))]
return request.make_response(pdf, headers=pdfhttpheaders)
elif converter == 'text':
text = report.with_context(context)._render_qweb_text(reportname, docids, data=data)[0]
texthttpheaders = [('Content-Type', 'text/plain'), ('Content-Length', len(text))]
return request.make_response(text, headers=texthttpheaders)
else:
raise werkzeug.exceptions.HTTPException(description='Converter %s not implemented.' % converter)