如何将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="' + filename + '.xlsx"' 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()方法就能把内存中的字节数据作为附件发送。
解决方案
修改代码核心逻辑:
- 保留
buffer.getvalue()的原始字节数据,无需转成bytearray - 使用
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
相关产品推荐
相关产品推荐

