django-wkhtmltopdf on a linux (Webfaction) server
Generating PDF with python is not an easy thing. Here is what I’ve tried:
- xhtml2pdf: the worst. It has a very bad CSS interpreter and it is pretty impossible to make a clean PDF out from a complex html page.
- WeasyPrint: that’s better. It has its own HTML and CSS2 interpreters, and despite some minor issues it is fairly reliable. However it requires some big dependencies, and I eventually had some memory issues on my webserver.
- wkhtmltopdf with its Django wrapper: for now, the best. It makes use of Webkit to render HTML+CSS+JS(!) pages, I don’t think you can do better. However, it requires QT, and this is big. Well, not the “classical” QT, a patched QT (that’s even worse) that allows to run without an X server. This is what I’m using for now in my projects
We’ll see here how to build wkhtmltopdf and a basic django-wkhtmltopdf
usage. These steps has been tested on a Webfaction server (CentOS 6) through SSH.
The easy way
Enter this command and go to the “Post-install” chapter.
1 | curl -fsSkL https://raw.github.com/gist/3608048/wkhtmltopdf.sh | sh |
It will install wkhtmltopdf in ~/bin
with its static libraries.
The hard way – Let’s build this
This is mostly taken from the wkhtmltopdf Wiki, but with some no-shared-libraries webserver specifics. Log on SSH, and let the magic begin.
Create a ~/download
folder
1 2 | $ mkdir -p ~/downloads $ cd ~/downloads |
Get wkhtmltopdf-qt:
1 2 3 4 | $ git clone git://gitorious.org/+wkhtml2pdf/qt/wkhtmltopdf-qt.git wkhtmltopdf-qt $ cd wkhtmltopdf-qt $ git checkout staging $ QTDIR=. ./bin/syncqt |
Configure, and build it! It will take some time (about an hour, which is not much as we disabled a lot of features):
1 2 3 | $ ./configure -release -static -fast -exceptions -no-accessibility -no-stl -no-sql-ibase -no-sql-mysql -no-sql-odbc -no-sql-psql -no-sql-sqlite -no-sql-sqlite2 -no-qt3support -xmlpatterns -no-phonon -no-phonon-backend -webkit -no-scripttools -no-mmx -no-3dnow -no-sse -no-sse2 -qt-zlib -qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -graphicssystem raster -opensource -nomake tools -nomake examples -nomake demos -nomake docs -nomake translations -no-opengl -no-dbus -no-multimedia -openssl -no-declarative -largefile -rpath -no-nis -no-cups -no-iconv -no-pch -no-gtkstyle -no-nas-sound -no-sm -no-xshape -no-xinerama -no-xcursor -no-xfixes -no-xrandr -no-mitshm -no-xinput -no-xkb -no-glib -no-openvg -no-xsync -no-audio-backend -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 -no-avx -no-neon -confirm-license -prefix "../wkqt" $ gmake -j3 $ gmake install |
Then, download wkhtmltopdf, and build it:
1 2 3 4 5 | $ cd ~/downloads $ git clone git://github.com/antialize/wkhtmltopdf.git wkhtmltopdf $ cd wkhtmltopdf $ ../wkqt/bin/qmake $ make |
You now have wkhtmltopdf and its static dependencies in ./bin/
. Let’s copy them into ~/bin
:
1 2 | $ mkdir -p ~/bin $ cp bin/* ~/bin/ |
Post-installation
We need ~/bin
in our $PATH
. That’s where django-wkhtmltopdf will look for. Add the following line in your ~/.bashrc
.
1 2 | export PATH=$HOME/bin:$PATH export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH |
And source it:
1 | $ source ~/.bashrc |
We’re done with wkhtmltopdf, let’s install its Django wrapper.
django-wkhtmltopdf
Go to your django app, and install django-wkhtmltopdf with PIP:
1 | $ pip install wkhtmltopdf |
Then, in your view:
1 2 3 4 | from wkhtmltopdf.views import PDFTemplateResponse def view(request): PDFTemplateResponse(request, template_name, context_dictionary).rendered_content |
Be careful, this last line of code is not documented in the django-wkhtmltopdf’s wiki. It may be subject to changes in future releases. However, that’s the only way I found to get a binary-string instead of a HttpResponse.
That’s all, folks !