使用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
相关产品推荐
相关产品推荐

