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

使用pisa生成PDF邮件发送报错:需str/bytes而非pisaContext

解决expected str, bytes or os.PathLike object, not pisaContext报错问题

这个报错的核心原因是你的render_to_pdf函数返回的是pisaContext对象,但mail.attach_file()方法需要的是文件路径字符串、字节流或者路径类对象,类型完全不匹配。下面是具体的修复方案:

1. 修改render_to_pdf函数,返回PDF字节数据

我们需要让函数返回生成好的PDF实际内容(bytes类型),而不是pisa的处理上下文。修改后的函数如下:

from io import BytesIO
from django.template.loader import get_template
import xhtml2pdf.pisa as pisa

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html = template.render(context_dict)
    result = BytesIO()
    
    # 将HTML渲染为PDF,写入到result字节流中
    pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
    
    if not pdf.err:
        result.seek(0)  # 将字节流的指针移到开头,确保能读取完整内容
        return result.getvalue()  # 返回bytes类型的PDF内容
    return None

2. 调整视图中的邮件附件添加逻辑

因为现在函数返回的是字节数据,不再是文件路径,所以不能再用attach_file()方法,改用attach()方法来直接添加字节形式的附件:

pdf_content = render_to_pdf('expenses/pdf_report.html', data)

if pdf_content:
    # 三个参数分别是:附件文件名、附件字节内容、MIME类型
    mail.attach('expense_report.pdf', pdf_content, 'application/pdf')
    mail.send()
else:
    # 这里可以添加PDF生成失败的处理逻辑,比如返回错误提示
    print("PDF生成失败,请检查模板或数据")

关键说明

  • result.getvalue()会从BytesIO中提取出所有字节数据,这正是邮件附件需要的bytes类型。
  • 调用result.seek(0)很重要:pisa在写入PDF内容后,字节流的指针会停在末尾,如果不重置到开头,虽然后续也能获取全部内容,但这是个好习惯,能避免某些边缘场景下的读取问题。
  • attach()方法适合直接传入内存中的字节内容,而attach_file()是专门用来读取本地文件路径的,两者要区分使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:22:32