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

如何将DataFrame作为附件通过Django发送?遇TypeError报错

解决DataFrame作为邮件附件发送时的TypeError问题

错误信息

TypeError: argument should be a str object or an os.PathLike object returning str, not <class 'bytes'>

原代码

df = df[['id','unit_id','receipt']]

with io.BytesIO() as buffer:
    with pd.ExcelWriter(buffer,engine='xlsxwriter') as writer:
        df.to_excel(writer,sheet_name=str(user.unidad) + ' - ' + str(user.unidad.unidad), index=False)
        writer.save()
        filename = 'Account statement'
        content_type = 'application/vnd.ms-excel'
        # archivo = HttpResponse(buffer.getvalue(), content_type=content_type)
        archivo = bytearray(buffer.getvalue())
        # archivo['Content-Disposition'] = 'attachment; filename=&quot;' + filename + '.xlsx&quot;'

subject = 'T500'
html_message = render_to_string('document_attachment.html')
plain_message = strip_tags(html_message)
from_email = 'no-reply@myemail.com'
to = [user.email]

msg = EmailMessage(
    subject,
    'Body message.',
    from_email,
    to,
)
msg.attach_file(archivo)
msg.send()

问题原因

EmailMessage.attach_file()方法要求传入文件路径字符串,但你传入的是字节数据(bytearray类型),这就触发了类型错误。不需要生成实体文件路径,直接用attach()方法就能把内存中的字节数据作为附件发送。

解决方案

修改代码核心逻辑:

  1. 保留buffer.getvalue()的原始字节数据,无需转成bytearray
  2. 使用msg.attach()替代msg.attach_file(),直接传入附件名、内容类型和字节数据

修改后的完整代码

import io
import pandas as pd
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.utils.html import strip_tags

df = df[['id','unit_id','receipt']]

filename = 'Account statement.xlsx'
content_type = 'application/vnd.ms-excel'

with io.BytesIO() as buffer:
    with pd.ExcelWriter(buffer, engine='xlsxwriter') as writer:
        df.to_excel(writer, sheet_name=f"{user.unidad} - {user.unidad.unidad}", index=False)
        writer.close()  # xlsxwriter推荐用close替代save,确保写入完成
        excel_data = buffer.getvalue()  # 直接获取内存中的Excel字节数据

subject = 'T500'
html_message = render_to_string('document_attachment.html')
plain_message = strip_tags(html_message)
from_email = 'no-reply@myemail.com'
to = [user.email]

msg = EmailMessage(
    subject,
    plain_message,  # 纯文本正文,提升邮件兼容性
    from_email,
    to,
)
# 可选:添加HTML格式的正文,让邮件同时支持两种格式
msg.attach_alternative(html_message, "text/html")
# 添加Excel附件
msg.attach(filename, excel_data, content_type)

msg.send()

关键说明

  • attach()方法参数顺序:附件文件名、附件字节数据、内容类型
  • 如果需要HTML邮件,必须用attach_alternative()单独添加HTML内容,同时保留纯文本版本
  • writer.close()是xlsxwriter引擎的标准做法,能确保所有数据写入到BytesIO中

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:55:19