django-wkhtmltopdf
django-wkhtmltopdf is a Django library that allows you to render HTML templates to PDF documents using the external `wkhtmltopdf` utility. It provides class-based views and utility functions for PDF generation within Django projects. The current version is 3.4.0, and it maintains a steady release cadence with a focus on stability and compatibility with newer Django versions.
Common errors
-
OSError: [Errno 2] No such file or directory: 'wkhtmltopdf'
cause The `wkhtmltopdf` binary is not found at the path specified in `WKHTMLTOPDF_CMD` or is not in the system's PATH.fixInstall `wkhtmltopdf` and ensure `WKHTMLTOPDF_CMD` in `settings.py` points to its correct absolute path. Verify the binary is executable. -
wkhtmltopdf exited with non-zero code 1. Output: ... Error: Failed to load URL ... (exit code: 1)
cause This generic error indicates `wkhtmltopdf` failed during processing. Common causes include inaccessible URLs (if using remote HTML), missing assets (CSS/images), JavaScript errors, or malformed HTML.fixCheck the `Output:` message for more details. Ensure all URLs in your HTML are accessible. Verify static files are correctly referenced. Try adding `--enable-javascript`, `--no-stop-slow-scripts` to `cmd_options` to diagnose JavaScript issues. -
TypeError: 'file' object is not callable
cause You might be trying to call `wkhtmltopdf` as a function directly from a file handle or a non-callable object, or mistaking the utility for a Python function.fixEnsure you are importing `wkhtmltopdf` from `wkhtmltopdf.utils` and calling it correctly, or using `PDFTemplateView` for class-based views. Do not try to execute the binary directly from Python in this manner. -
django.template.exceptions.TemplateSyntaxError: Invalid block tag on line X: 'load static', expected 'empty' or 'endif'
cause This error occurs when the template renderer can't find the `staticfiles` app, usually because it's missing from `INSTALLED_APPS` or the template tags are incorrect.fixEnsure `'django.contrib.staticfiles'` is included in your `INSTALLED_APPS` in `settings.py`. Double-check `{% load static %}` at the top of your template and correct usage of `{% static 'path/to/file.css' %}`.
Warnings
- breaking The `wkhtmltopdf` binary is no longer automatically downloaded or managed by the library as of version 3.0.0. It must be installed separately on your system.
- gotcha Failure to set `WKHTMLTOPDF_CMD` in Django settings or setting it to an incorrect path will result in `OSError: [Errno 2] No such file or directory` or similar errors when attempting to generate a PDF.
- gotcha Relative paths for static files (CSS, images) in your HTML templates may not render correctly in the generated PDF due to `wkhtmltopdf`'s security restrictions or inability to resolve Django's static URLs.
- gotcha There are known rendering differences between `wkhtmltopdf` versions. Specifically, `wkhtmltopdf` 0.12.6 is often recommended for stability and feature completeness, while newer versions (e.g., 0.13.0-alpha) might introduce regressions or require different flags.
Install
-
pip install django-wkhtmltopdf
Imports
- PDFTemplateView
from wkhtmltopdf.views import PDFTemplateView
- PDFView
from wkhtmltopdf.views import PDFView
- wkhtmltopdf
from wkhtmltopdf.utils import wkhtmltopdf
Quickstart
import os
from django.conf import settings
from django.urls import path
from django.views.generic import TemplateView
from wkhtmltopdf.views import PDFTemplateView
# Minimal Django settings for demonstration
settings.configure(
DEBUG=True,
INSTALLED_APPS=[
'django.contrib.staticfiles',
'wkhtmltopdf'
],
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
'APP_DIRS': True,
},
],
STATIC_URL='/static/',
WKHTMLTOPDF_CMD=os.environ.get('WKHTMLTOPDF_CMD', '/usr/local/bin/wkhtmltopdf') # IMPORTANT: Set this to your wkhtmltopdf binary path
)
# Create a dummy template file for the quickstart
os.makedirs(os.path.join(os.path.dirname(__file__), 'templates'), exist_ok=True)
with open(os.path.join(os.path.dirname(__file__), 'templates', 'hello_pdf.html'), 'w') as f:
f.write('<h1>Hello, PDF!</h1><p>Generated by django-wkhtmltopdf.</p>')
urlpatterns = [
path(
'pdf-view/',
PDFTemplateView.as_view(
template_name='hello_pdf.html',
filename='my_document.pdf',
header_html='<p>Header</p>',
footer_html='<p>Footer</p>',
show_as_attachment=True,
cmd_options={'enable-local-file-access': True}
),
name='pdf_view'
),
path(
'html-view/',
TemplateView.as_view(template_name='hello_pdf.html'),
name='html_view'
)
]
# To run this minimal example (for testing):
# from django.core.management import execute_from_command_line
# if __name__ == '__main__':
# execute_from_command_line(['manage.py', 'runserver', '--noreload'])
# To access: Navigate to /pdf-view/ after setting up Django and wkhtmltopdf