You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo如何在浏览器打印CSV报表?求控制器实现示例

实现Odoo浏览器直接下载CSV报表的控制器示例

我明白你的需求——现在你的CSV是存在Odoo运行机器的本地路径里,但你想让用户点击按钮后直接在浏览器弹出下载框对吧?用Odoo控制器完全能实现这个需求,我给你一套完整的示例方案,分模块说明:

1. 优先推荐:直接在模型方法中返回下载响应

这种方式不需要额外写独立控制器,代码更简洁,直接在模型方法里生成CSV内容并返回HTTP下载响应:

from odoo import models
import csv
from io import StringIO

class AccountInvoice(models.Model):
    _inherit = 'account.invoice'

    def action_download_csv(self):
        # 把CSV内容写入内存流,避免操作本地文件
        output = StringIO()
        csv_writer = csv.writer(output, delimiter=',')
        # 写入表头
        csv_writer.writerow(['Product Name','Price Unit','Quantity'])
        # 逐行写入发票明细数据
        for line in self.invoice_line_ids:
            csv_writer.writerow([line.product_id.name, line.price_unit, line.quantity])
        # 重置流指针到起始位置
        output.seek(0)
        csv_content = output.getvalue()
        
        # 生成Odoo HTTP响应,指定下载头让浏览器识别为附件
        return self.env['ir.http'].make_response(
            csv_content,
            headers=[
                ('Content-Type', 'text/csv'),
                ('Content-Disposition', f'attachment; filename="invoice_{self.name}_details.csv"'),
            ]
        )

2. 可选方案:使用独立控制器路由

如果你需要更复杂的业务逻辑(比如批量处理、权限校验等),可以单独写一个控制器类:

首先在你的模块下创建controllers/main.py文件:

from odoo import http
from odoo.http import request
import csv
from io import StringIO

class InvoiceCSVController(http.Controller):
    # 定义路由,指定用户权限验证
    @http.route('/account/invoice/download_csv/<int:invoice_id>', type='http', auth='user')
    def download_invoice_csv(self, invoice_id, **kwargs):
        # 获取目标发票记录,做存在性校验
        invoice = request.env['account.invoice'].browse(invoice_id)
        if not invoice.exists():
            return request.not_found()
        
        # 生成CSV内容
        output = StringIO()
        csv_writer = csv.writer(output, delimiter=',')
        csv_writer.writerow(['Product Name','Price Unit','Quantity'])
        for line in invoice.invoice_line_ids:
            csv_writer.writerow([line.product_id.name, line.price_unit, line.quantity])
        output.seek(0)
        csv_content = output.getvalue()
        
        # 返回下载响应
        return request.make_response(
            csv_content,
            headers=[
                ('Content-Type', 'text/csv'),
                ('Content-Disposition', f'attachment; filename="invoice_{invoice.name}_details.csv"'),
            ]
        )

然后修改模型里的按钮方法,重定向到这个控制器路由:

def action_download_csv(self):
    return {
        'type': 'ir.actions.act_url',
        'url': f'/account/invoice/download_csv/{self.id}',
        'target': 'self',
    }

3. 更新视图按钮配置

最后确保你的发票视图里的按钮绑定了新的方法:

<button name="action_download_csv" string="Download CSV" type="object" class="oe_highlight"/>

这样用户点击按钮后,浏览器就会直接弹出下载对话框,再也不会把文件存到服务器本地啦!如果需要支持批量选中发票下载,只要调整代码遍历self(多记录集)即可。

内容的提问来源于stack exchange,提问作者code_explorer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:55