Generate PDF from HTML using Django and Reportlab
UPDATE for 2021:
Since this answer is over half a decade old, some new solutions have become available. These days, I tend to use WeasyPrint, which has the additional benefit of being BSD licensed instead of LGPL. It is a tad slower, however.
ORIGINAL ANSWER:
I'd recommend using wkhtmltopdf.
The short answer? On Ubuntu, install a binary:
apt-get install wkhtmltopdf
On CentOS / RedHat:
yum install wkhtmltox-0.12.2.1_linux-centos6-amd64.rpm
Then pip install a Python package:
pip install pdfkit
Then the code:
import pdfkit
input_filename = 'README.html'
output_filename = 'README.pdf'
with open(input_filename, 'r') as f:
html_text = f.read()
pdfkit.from_string(html_text, output_filename)
For the long answer and details, I put together a blog post:
https://www.pyphilly.org/generating-pdf-markdown-or-html/
That should take care of the PDF creation; you'll have to decide how you want to handle the download. Good luck!
Comments
-
Dr Mouse almost 2 years
I am coming back with a new question which I am unable to answer, having scratched my head the whole day on it.
I want to generate a PDF from a webpage by clicking on a "Download PDF" button. I tried several modules including Reportlab and XHTML2PDF but I am not able to generate any pdf nor downloading it... Here is what I did with Reportlab, following Render HTML to PDF in Django site
-- views.py --
import cStringIO as StringIO import ho.pisa as pisa from django.template.loader import get_template from django.template import Context from django.http import HttpResponse from cgi import escape def index_data(request): #Code to generate data return render(request, "analytics/stat.html", locals()) return render_to_pdf( 'analytics/stat.html', { 'pagesize':'A4', 'mylist': results, } ) def render_to_pdf(template_src, context_dict): template = get_template(template_src) context = Context(context_dict) html = template.render(context) result = StringIO.StringIO() pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), result) if not pdf.err: return HttpResponse(result.getvalue(), content_type='application/pdf') return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
-- urls.py --
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', "analytics.views.main_page", name="main_page"), url(r'^portail/$', "analytics.views.index_data", name="index"), url(r'^generate_pdf/$', "analytics.views.GroupPDFGenerate.as_view()", name="generate_pdf")
]
-- Template analytics/stat.html --
{% extends "analytics/layout.html" %} {% block title %} Audience {% endblock title %} {% block head %} # Script to generate google charts {% endblock head %} {% block body %} <div class="page-header"> <h1 align="center"> Audience </h1> </div> <div class="row"> <div class="col-md-1"> <h3 align="center"><a href="/logout/">Logout</a></h3> <h3 align="center"><a href="statistiques.pdf">Download pdf</a></h3> </div> </div> {% endblock %}
Also, is there a better module to process ?
-
Dr Mouse almost 9 yearsMany thanks ! It seems pretty straightforward to use ! How would you integrate the code with Django ? Through a view ?
-
FlipperPA almost 9 yearsThat would depend on what you're doing, but yes, most likely in a view.
-
metakermit about 7 yearsOne problem I have with wkhtmltopdf is that it requires an external binary which is problematic to deploy to services like Heroku.
-
ZF007 over 4 years@FlipperPA ... link peregrinesalon.com/blog/2015/06/… nolonger working. Please update.
-
FlipperPA over 4 years@metakermit @ZF007 I've updated the link to the blog post. An alternative to
pdfkit
/wkhtmltopdf
isweasyprint
, although it has pre-reqs which can be tricky as well: weasyprint.org -
FlipperPA about 3 years@SharanArumugam Over the past few years, I've switched to using Weasyprint, which is BSD licensed. weasyprint.org
-
Sharan Arumugam about 3 yearsthank you @FlipperPA for the update, unfortunately, in windows, we need GTK runtime to use weasyprint, and this again ends up being a LGPL again!