从JavaScript调用Odoo报表无打印输出的原因排查
问题:JavaScript调用Odoo报表函数后报表不打印
我开发了一个针对stock.move.line元素生成报表的向导,从列表视图调用时运行正常。现在希望通过条码界面的按钮触发JavaScript调用该报表(点击每个stock.move.line对应的按钮时执行)。尝试调用时,Python函数已被触发(服务器控制台能看到print()输出),但报表并未实际打印。单独测试Python函数是有效的。
点击界面按钮时,浏览器控制台能看到正确的nb_printing和stock_move_line值,服务器控制台也能看到"Hello, function is launched."输出,但报表就是不打印。
相关代码
JavaScript代码
odoo.define("colona_custo.print_product_label", function(require) { "use strict"; var rpc = require("web.rpc"); function call_print_function(nb_printing, move_line_id) { console.log(nb_printing); console.log(move_line_id); return rpc.query({ model: 'print.product.label.wizard', method: 'print_product_label_from_js', args: [[], nb_printing, move_line_id] }); } function print_product_label() { var move_line_id = $(this).next().text(); // 询问用户打印次数 $(document.body).append("<div id='warning_popup' style='background: rgba(255, 255, 255, 0.9); width: 50vw; height: 50vh; border-radius: 5px; padding: 10px; z-index: 1000; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'><h2 style='position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'>How many times do you want to print the product label?</h2><input id='user_entry' style='position:relative;top:50%;left:45%;'/><button id='action_print' style='position: absolute; bottom: 5px; left: 100px;' class='btn btn-primary'>Print</button><button id='close_popup_printing' style='position: absolute; bottom: 5px; left: 5px;' class='btn btn-primary'>Close</button></div>") $('#close_popup_printing').on('click', function() { $('#warning_popup').hide(); }); $('#action_print').on('click', function() { var nb_printing = $('#user_entry').val(); if (nb_printing > 0) { call_print_function(nb_printing, move_line_id); } }); } $(document).on('click', '.o_button_print_product_label', print_product_label)});
Python代码
from odoo import api, fields, models from odoo.exceptions import UserError class SmlPrintProductLabelWizard(models.TransientModel): _name = 'print.product.label.wizard' nb_printing = fields.Integer() def print_product_label(self): if (self.nb_printing >= 0): return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': self.env.context.get('active_id'), 'nb_printing': self.nb_printing}) else: raise UserError("The number of printing is incorrect.") def print_product_label_from_js(self, nb_printing=1, move_line_id=34): print("===========================") print("Hello, function is launched.") return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': int(move_line_id), 'nb_printing': int(nb_printing)})
问题原因与解决方法
核心原因
Odoo的report_action返回的是一个动作字典,列表视图调用时Odoo前端框架会自动处理这个字典并触发报表,但自定义JavaScript的RPC调用仅获取了字典,没有在前端执行对应的动作逻辑,所以报表不会被触发。
解决步骤
1. 修改JavaScript代码,处理RPC返回的动作
引入ActionManager并在RPC回调中执行报表动作:
odoo.define("colona_custo.print_product_label", function(require) { "use strict"; var rpc = require("web.rpc"); var ActionManager = require('web.ActionManager'); // 新增引入 function call_print_function(nb_printing, move_line_id) { console.log(nb_printing); console.log(move_line_id); return rpc.query({ model: 'print.product.label.wizard', method: 'print_product_label_from_js', args: [[], nb_printing, move_line_id] }).then(function(action) { // 用ActionManager执行报表动作 var actionManager = new ActionManager(); actionManager.doAction(action); // 执行后关闭弹窗 $('#warning_popup').hide(); }).catch(function(error) { console.error('打印出错:', error); }); } // 其余代码保持不变 function print_product_label() { var move_line_id = $(this).next().text(); $(document.body).append("<div id='warning_popup' style='background: rgba(255, 255, 255, 0.9); width: 50vw; height: 50vh; border-radius: 5px; padding: 10px; z-index: 1000; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'><h2 style='position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);'>How many times do you want to print the product label?</h2><input id='user_entry' style='position:relative;top:50%;left:45%;'/><button id='action_print' style='position: absolute; bottom: 5px; left: 100px;' class='btn btn-primary'>Print</button><button id='close_popup_printing' style='position: absolute; bottom: 5px; left: 5px;' class='btn btn-primary'>Close</button></div>") $('#close_popup_printing').on('click', function() { $('#warning_popup').hide(); }); $('#action_print').on('click', function() { var nb_printing = $('#user_entry').val(); if (nb_printing > 0) { call_print_function(nb_printing, move_line_id); } }); } $(document).on('click', '.o_button_print_product_label', print_product_label)});
2. 优化Python方法(可选)
给print_product_label_from_js添加@api.model装饰器,明确为模型级方法:
@api.model def print_product_label_from_js(self, nb_printing=1, move_line_id=34): print("===========================") print("Hello, function is launched.") return self.env.ref('colona_custo.action_report_product_label').report_action([], data={'stock_move_line_id': int(move_line_id), 'nb_printing': int(nb_printing)})
3. 额外优化建议
- 增加用户输入校验,确保
nb_printing是有效整数,避免类型转换错误。 - 弹窗可以使用Odoo自带的弹窗组件(如
Dialog),替代原生DOM拼接,提升兼容性和风格统一。
内容的提问来源于stack exchange,提问作者tlelubre
相关产品推荐
相关产品推荐

