如何在Odoo 16中通过公开URL渲染自定义QWeb报表
Odoo 16 自定义报表公开URL访问问题解决
问题分析
你已基于account.move模型创建了自定义QWeb PDF报表,但自行编写的控制器无法通过带access_token的公开URL正常访问。原控制器存在以下核心问题:
- 未验证URL中的
access_token,直接用sudo()获取记录,绕过了权限校验逻辑 - 未处理URL中的
report_type参数,无法匹配内置报表的访问逻辑 - 记录存在性校验方式错误,渲染报表时误用了HTML渲染方法而非PDF
- 权限检查逻辑不符合Odoo公开URL的安全验证规范
修正后的控制器代码
from odoo import http from odoo.http import request class CustomVendorBillReport(http.Controller): @http.route(['/my/custom_vendor_bills/<int:move_id>'], type='http', auth="public", website=True) def custom_vendor_bill_report(self, move_id, access_token=None, report_type='pdf', **kw): # 使用public环境获取记录,避免sudo绕过权限 move = request.env['account.move'].browse(move_id) # 校验记录存在性和access_token有效性 if not move.exists() or not move._check_access_token(access_token): return request.redirect('/my') # 根据report_type选择渲染方式 report_ref = request.env.ref('module_name.report_account_move_action') if report_type == 'pdf': pdf_content, _ = report_ref._render_qweb_pdf([move_id]) headers = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf_content))] else: html_content, _ = report_ref._render_qweb_html([move_id]) headers = [('Content-Type', 'text/html'), ('Content-Length', len(html_content))] return request.make_response(pdf_content if report_type == 'pdf' else html_content, headers=headers)
关键修正点说明
- Access Token验证:使用Odoo内置的
_check_access_token方法验证URL中的token,这是Odoo公开报表URL的标准校验方式,确保只有持有有效token的请求才能访问。 - 环境权限控制:去掉
sudo(),使用public用户环境直接获取记录,配合token校验保证权限安全。 - Report Type处理:接收URL中的
report_type参数,支持PDF和HTML两种格式渲染,与内置报表行为保持一致。 - 报表引用方式:直接引用你定义的
ir.actions.report记录(report_account_move_action),而非通过ir.actions.report模型泛用渲染,确保使用正确的纸张格式和报表配置。 - 存在性校验:使用
exists()方法检查记录是否真实存在,避免空记录集导致的逻辑错误。
额外注意事项
- 确保代码中的
module_name替换为你的实际模块名称,且report_account_move_action是你自定义报表动作的正确ID。 - 测试时需使用目标
account.move记录的有效access_token,该值可从对应记录的access_token字段获取。
内容的提问来源于stack exchange,提问作者hardik device
相关产品推荐
相关产品推荐

