Django,ReportLab PDF生成并附加到电子邮件上

11

如何最好地使用Django和ReportLab生成PDF并将其附加到电子邮件消息?

我正在使用SimpleDocTemplate,并可以将生成的PDF附加到我的HttpResponse中 - 这很好,但我无法找到如何将同样的附件添加到电子邮件的确切方法:

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=invoice.pdf'
    doc = SimpleDocTemplate(response, pagesize=letter)
    Document = []

我想通过将表格添加到文档中来制作PDF文件...

  doc.build(Document)
  email = EmailMessage('Hello', 'Body', 'from@from.com', ['to@to.com'])
  email.attach('invoice.pdf', ???, 'application/pdf')
  email.send()
我不确定如何将我的pdf文档转换为blob,以便于email.attach接受并通过email.send发送。 有什么想法吗?

我在stackoverflow上看到了几个其他问题有类似的提问,但没有找到好的答案... - Daniel D
3个回答

10
使用ReportLab

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch

def createPDF(request):
 x=100
 y=100
 buffer=StringIO()
 p=canvas.Canvas(buffer,pagesize=letter)
 p.drawString(x,y,"HELLOWORLD")
 p.showPage()
 p.save() 
 pdf=buffer.getvalue()
 buffer.close() 
 return pdf

def someView(request):
 EmailMsg=mail.EmailMessage(YourSubject,YourEmailBodyCopy,'email@email.com',["email@email.com"],headers={'Reply-To':'email@email.com'})
 pdf=createPDF(request)
 EmailMsg.attach('yourChoosenFileName.pdf',pdf,'application/pdf')
 EmailMsg.send()

完美地运行!!

6

好的 - 我根据一些拼凑起来的东西弄清楚了 -

首先 - 我的要求: - 我只想在内存中创建PDF - 我不想让文件挂在那里,因为它们占用空间,而且我不想让可能是敏感数据的东西无保护地挂在服务器上。

所以 - 我选择了ReportLab和Platypus功能来生成我的文档。我已经投入足够的时间了,现在很容易。所以这是我的方法,让我使用ReportLab中的DocTempates,允许我使用Django的电子邮件功能发送电子邮件。

这是我的做法:

 # Create the PDF object, using the buffer object as its "file."
  buffer = StringIO()
  doc = SimpleDocTemplate(buffer, pagesize=letter)
  Document = []

  # CRUFT PDF Data

  doc.build(Document)
  pdf = buffer.getvalue()
  buffer.close()

  email = EmailMessage('Hello', 'Body', 'from@from.com', ['to@to.com'])
  email.attach('invoicex.pdf', pdf , 'application/pdf')
  email.send()

我从网页生成转向电子邮件生成时遇到的问题是如何获取可以“附加”到电子邮件中的正确对象。创建一个缓冲区,然后从缓冲区中获取数据解决了我的问题...


对于使用Python3的用户,必须使用BytesIO对象而不是StringIO,因为字节和字符串不兼容。 - Yogi Bear

3

我没有看到您的 blob 渲染在哪里,因此无法建议您如何导入它。我使用 Pisa 和 StringIO 取得了很好的效果:

import ho.pisa as pisa
import StringIO
from django.template.loader import render_to_string
from django.core.mail import EmailMessage

render = render_to_string("books/agreement/agreement_base.html",
                              { "title": book.title,
                                "distribution": book.distribution_region })
out = StringIO.StringIO()
pdf = pisa.CreatePDF(StringIO.StringIO(render), out)
email = EmailMessage('Hello', 'Body', 'from@from.com', ['to@to.com'])
email.attach('agreement.pdf', out.getvalue(), 'application/pdf')
email.send()

如果你的PDF文档作为一个独立的、持久的文件存在于你的文件系统中,那么你不就可以:
email.attach('agreement.pdf', open('agreement.pdf', 'rb').read(), 'application/pdf')

我稍微更新了一下我的内容,但是我不确定在响应对象、SimpleDocTemplate 对象或任何其他对象上存在什么方法可以获取可以附加到消息的东西。 - Daniel D
我尝试了您的解决方案。但它会在 PDF 文件中呈现我的 HTML 模板。您知道这是为什么吗? - silviomoreto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接