7
votes

I'm using wkhtmltopdf wrapper to generate template into PDF in Django 1.6. It works fine when I want to display the PDF afterwards or send the PDF file with HttpResponse for download but what I want to do is to create the file in my tmp folder and attach it to an email.

I'm not sure how to achieve this.

# views.py

context = {
    'products_dict': products_dict,
    'main_categories': main_categories,
    'user_category': user_category
}

response = PDFTemplateResponse(request=request,
                               context=context,
                               template="my_template.html",
                               filename="filename.pdf",
                               show_content_in_browser=True,
                               cmd_options={'encoding': 'utf8',
                                            'quiet': True,
                                            'orientation': 'landscape',
                                           }
                               )

return response

The code above generate the PDF exactly how I want it. The thing is I don't want to display the PDF in the browser or start a download (I don't want to return response). I just want to create it and then attach the file to an email like this:

email = EmailMessage()
email.subject = "subject"
email.body = "Your PDF"
email.from_email = "[email protected]"
email.to = [ "[email protected]", ]

# Attach PDF file to the email
email.attach_file(my_pdf_file_here)
# Send email
email.send()

I tried to use subprocess but it doesn't seem like I can send context to my template to render it before generating the PDF.

EDIT (SOLUTION): Thanks to Daniel Roseman for the help to go towards what I wanted. I did use the tests file of wkhtmltopdf here: http://pydoc.net/Python/django-wkhtmltopdf/1.1/wkhtmltopdf.tests.tests/

This is what I did in my view:

order = Order.objects.get(id=order_id)
return_file = "tmp/" + 'order' + str(order_id) + '.pdf'

context = {
    'order' : order,
    'items' : order.ordered_products.all()
}

response = PDFTemplateResponse(request=request, 
                               context=context, 
                               template="'products/order_pdf.html'",
                               cmd_options={ 'encoding': 'utf8',
                                             'quiet': True
                                           }
                               )

temp_file = response.render_to_temporary_file("products/order_pdf.html")

wkhtmltopdf(pages=[temp_file.name], output=return_file)

You can then use the return_file in email.attach() method like this:

email.attach_file(return_file)

You can also omit output parameter in the wkhtmltopdf method. Then the method will return the output and use this output in attach_file() method.

3
You can do this by encode pdf file with base64 and appending to message body.Sencer H.
Attaching the file to the email is not a problem. The problem is to create the PDF file with wkhtmltopdf without returning an HttpResponse or using a URL/Class-based viewdguay
Oh! Im sorry. Can't you just write output of the wkhtmtopdf to into a file in binary mode?Sencer H.
I don't know how to produce the PDF output in my view without returning HttpResponsedguay
In your example, return is not looks like HttpResponse. Unless if wkhtmltopdf output is. If output of wk is HttpResponse object I guess you need to do some workaround.Sencer H.

3 Answers

4
votes

Your issue is not with wkhtmltopdf, but the django-wkhtmltopdf which provides some class-based views that it renders with wkhtmltopdf. If you don't want a view, you don't need to use them: you could just render the template yourself and pass the result string to the command-line wkhtmltopdf tool.

It looks like the django-wkhtmltopdf library does provide some utility functions (in the utils directory) which might make that last stage a bit easier.

-1
votes

Hey Please check your wkhtmltopdf binary is it executable or not. as this PDFTemplateResponse worked for me.

-1
votes
response = PDFTemplateResponse(
    request,
    template='reports/report_email.html',
    filename='weekly_report.pdf',
    context=render_data,
    cmd_options={'load-error-handling': 'ignore'})



subject, from_email, to = 'reports', '[email protected]', '[email protected]'
html_content = render_to_string('reports/report_email.html',render_data)
text_content = strip_tags(html_content)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.attach('pdf_filename.pdf', response.rendered_content, 'application/pdf')
msg.send()

this code snippet may help you after placing it in views.py.