Odoo14模型自定义方法如何返回变量实现弹窗展示
问题原因
Odoo 14中自定义方法返回的窗口动作不符合框架规范,是弹窗无法正常加载的核心原因:
res_model配置为不存在的my.model,框架找不到对应模型资源直接加载失败views参数格式错误,合法格式为[(视图ID, 视图类型)],直接传入统计变量列表无法被框架识别,也无法完成值传递- Odoo标准窗口动作默认从绑定模型拉取记录渲染视图,没有配套的传值、视图匹配逻辑,自然无法展示你统计的发送数值
另外代码存在两个小问题:
- 日志初始化逻辑每次调用方法都会重复添加文件处理器,多次触发会导致同一条日志被重复写入多次
- 遍历记录的逻辑可以简化,按钮触发的方法中
self本身就是选中的销售订单记录集,不需要从context取active_ids再二次browse,直接遍历self即可减少不必要的数据库查询
修复方案
提供两种可直接运行的实现方式,按需选择即可:
方案1:轻量实现(无需新建额外文件)
直接使用Odoo内置的客户端弹窗动作,不需要新增模型、视图文件,仅修改原方法代码即可。
如果需要居中模态弹窗展示结果,直接替换原方法末尾的return部分,同时修复日志问题即可,完整修改后的方法代码如下:
from odoo import models import logging class SaleOrder(models.Model): _inherit = "sale.order" _description = "Sales order custom proforma multiple" def send_multiple_profoma_invoice(self): template_id = self._find_mail_template() logger = logging.getLogger("output") if not logger.handlers: logger.setLevel(logging.DEBUG) fh = logging.FileHandler('/mnt/extra-addons/output.log') fh.setLevel(logging.DEBUG) logger.addHandler(fh) mail_sent, mail_err = 0, 0 for sale_order in self: try: sale_order.with_context( force_send=True ).message_post_with_template( template_id, composition_mode='comment', email_layout_xmlid="mail.mail_notification_paynow" ) mail_sent += 1 logger.info(f'The email is sent {str(sale_order)}') except Exception as e: mail_err += 1 logger.error(e.with_traceback(e.__traceback__)) # 模态弹窗返回 message = f""" <div class="p-3"> <div class="mb-2"><i class="fa fa-check-circle text-success mr-2"/> 发送成功数量:{mail_sent}</div> <div><i class="fa fa-times-circle text-danger mr-2"/> 发送失败数量:{mail_err}</div> </div> """ return { 'type': 'ir.actions.client', 'tag': 'dialog', 'params': { 'title': '批量形式发票发送结果', '$content': message, 'size': 'small', 'buttons': [ { 'text': '确定', 'classes': 'btn btn-primary', 'close': True } ] } }
如果只需要右上角常驻通知提示,可以把弹窗返回部分替换为以下代码:
return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': '批量形式发票发送结果', 'message': f'发送成功:{mail_sent} 封 | 发送失败:{mail_err} 封', 'sticky': True, 'type': 'success' if mail_err == 0 else 'warning', } }
方案2:标准向导实现(适合后续扩展功能)
如果后续需要在结果页增加失败记录跳转、重试发送等功能,使用Odoo标准的瞬态模型(TransientModel)实现向导弹窗:
- 在模块下新建
wizard目录,创建send_result_wizard.py:
from odoo import models, fields class SendProformaResultWizard(models.TransientModel): _name = 'send.proforma.result.wizard' _description = '批量发送形式发票结果' mail_sent = fields.Integer(string='发送成功数量', readonly=True) mail_err = fields.Integer(string='发送失败数量', readonly=True)
- 在
wizard目录下新建send_result_wizard_views.xml,添加表单视图:
<odoo> <record id="view_send_proforma_result_wizard_form" model="ir.ui.view"> <field name="name">send.proforma.result.wizard.form</field> <field name="model">send.proforma.result.wizard</field> <field name="arch" type="xml"> <form string="发送结果"> <group> <field name="mail_sent"/> <field name="mail_err"/> </group> <footer> <button string="确定" class="btn-primary" special="cancel"/> </footer> </form> </field> </record> </odoo>
- 修改原方法的返回逻辑,循环结束后创建向导记录并返回打开动作:
# 发送循环结束后添加 result_wizard = self.env['send.proforma.result.wizard'].create({ 'mail_sent': mail_sent, 'mail_err': mail_err }) return { 'type': 'ir.actions.act_window', 'name': '批量形式发票发送结果', 'view_mode': 'form', 'res_model': 'send.proforma.result.wizard', 'res_id': result_wizard.id, 'view_id': self.env.ref('你的模块技术名.view_send_proforma_result_wizard_form').id, 'target': 'new', }
注意需要把代码里的你的模块技术名替换为实际模块的技术名称,同时将新建的wizard py文件加入模块__init__.py的导入列表,视图文件加入__manifest__.py的data列表后升级模块即可生效。
内容的提问来源于stack exchange,提问作者Elunemoon
相关产品推荐
相关产品推荐

