如何在不使用向导的情况下从表单视图打印Excel文件?按钮触发异常
解决Odoo表单视图无向导导出Excel时按钮触发重复弹窗问题
嘿,我看你在Odoo里折腾表单直接导出Excel的功能时碰到了麻烦——点击generate_bt按钮后居然弹出了重复的表单视图,而不是生成下载Excel对吧?这问题我之前帮人解决过,给你梳理下怎么搞定:
问题复盘
你的需求是不使用向导,直接从表单视图导出Excel文件,但当前点击按钮后,原本的表单视图以弹窗形式重复出现,完全没触发Excel生成逻辑。
问题根源
这种情况大概率是两个原因:
- 按钮的XML配置参数不对,Odoo默认触发了表单弹窗,没执行你的Python导出方法
- 你的Excel生成方法没有返回正确的文件下载响应,导致页面 fallback 到了默认的表单渲染行为
分步解决方案
1. 先把按钮的XML配置改对
首先检查你视图里的按钮定义,要确保type和target参数设置正确,避免触发弹窗:
<button name="action_generate_excel" string="Generate Excel" type="object" target="new" class="oe_highlight"/>
type="object":告诉Odoo这个按钮要调用Python对象方法,不是打开视图或者动作target="new":让文件下载在新窗口打开,避免影响当前表单页面- 注意按钮的
name必须和你Python里的方法名完全一致!
2. 修正Python导出方法的返回值
你的Excel生成逻辑没问题,但关键是要返回文件下载的动作响应,而不是让Odoo默认渲染表单。这里给你调整后的完整代码示例:
# -*- coding: utf-8 -*- from odoo import models, fields, api from odoo.tools.translate import _ from odoo.exceptions import UserError, AccessError from datetime import datetime, timedelta import dateutil.parser import base64 import xlwt from io import BytesIO # Python3用这个,Python2替换成from cStringIO import StringIO import logging _logger = logging.getLogger(__name__) class YourModel(models.Model): _name = 'your.model.name' # 替换成你的实际模型名 _description = 'Your Model Description' # 这里放你的字段定义,比如: name = fields.Char(string="Name") # ...其他字段... def action_generate_excel(self): # --- 1. 生成Excel内容的逻辑(你可以替换成自己的业务逻辑)--- wb = xlwt.Workbook(encoding='utf-8') ws = wb.add_sheet('表单数据报表') # 写入表头 ws.write(0, 0, '记录ID') ws.write(0, 1, '名称') # 写入当前表单的数据(如果是批量可以循环self) ws.write(1, 0, self.id) ws.write(1, 1, self.name) # --- 2. 将Excel写入内存流 --- output = BytesIO() wb.save(output) output.seek(0) # 重置流指针到开头 # --- 3. 准备文件下载响应 --- # 生成带时间戳的文件名,避免重复 filename = f"表单报表_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xls" # 把文件流转成base64格式 file_data = base64.b64encode(output.getvalue()) # --- 4. 返回正确的下载动作,避免弹窗 --- return { 'type': 'ir.actions.act_url', 'url': 'web/content/?model=your.model.name&id=%s&field=excel_file&download=true&filename=%s' % (self.id, filename), 'target': 'new', }
3. 关键注意事项
- 如果是Python2环境,把
from io import BytesIO换成from cStringIO import StringIO - 绝对不要让方法返回
self或者其他会触发表单渲染的内容,必须返回文件下载的动作 - 可以在方法里加
_logger.info("Excel生成方法被调用"),查看Odoo日志确认方法是否被正确触发
额外排查点
如果还是弹出表单弹窗,那你要检查:
- 是否有其他视图继承或者自定义JS代码修改了这个按钮的行为
- 确认按钮的
name和Python方法名完全匹配,大小写都不能错
内容的提问来源于stack exchange,提问作者vbt
相关产品推荐
相关产品推荐

