{"id":8957,"library":"django-weasyprint","title":"Django WeasyPrint Integration","description":"django-weasyprint is a Django application that integrates WeasyPrint, allowing developers to generate PDF documents from HTML and CSS templates within their Django projects. It provides class-based views and response classes to streamline the process of converting rendered Django templates into PDF files. The current version is 2.5.0, with a release cadence tied to major WeasyPrint and Django releases, supporting modern Python and Django versions.","status":"active","version":"2.5.0","language":"en","source_language":"en","source_url":"https://github.com/fdemmer/django-weasyprint","tags":["Django","PDF","WeasyPrint","reporting","HTML to PDF"],"install":[{"cmd":"pip install django-weasyprint","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Web framework integration","package":"Django","optional":false},{"reason":"Core HTML to PDF rendering engine. Requires system dependencies like Pango and GTK+ on the host OS.","package":"WeasyPrint","optional":false}],"imports":[{"symbol":"WeasyTemplateResponseMixin","correct":"from django_weasyprint.views import WeasyTemplateResponseMixin"},{"symbol":"WeasyTemplateResponse","correct":"from django_weasyprint.views import WeasyTemplateResponse"},{"note":"The function `django_url_fetcher` was replaced by the `DjangoURLFetcher` class in v2.5.0 to align with WeasyPrint 68's API changes.","wrong":"from django_weasyprint.utils import django_url_fetcher","symbol":"DjangoURLFetcher","correct":"from django_weasyprint.urlfetcher import DjangoURLFetcher"}],"quickstart":{"code":"import os\nfrom django.db import models\nfrom django.shortcuts import render\nfrom django.urls import path\nfrom django.views.generic import DetailView\nfrom django_weasyprint.views import WeasyTemplateResponseMixin, WeasyTemplateResponse\n\n# models.py (example)\nclass Product(models.Model):\n    name = models.CharField(max_length=255)\n    description = models.TextField()\n    price = models.DecimalField(max_digits=10, decimal_places=2)\n\n    def __str__(self):\n        return self.name\n\n# views.py\nclass ProductDetailView(DetailView):\n    model = Product\n    template_name = 'products/product_detail.html'\n    context_object_name = 'product'\n\nclass ProductPDFView(WeasyTemplateResponseMixin, ProductDetailView):\n    # PDF-specific settings\n    pdf_stylesheets = [\n        os.path.join(os.environ.get('STATIC_ROOT', ''), 'css/pdf_styles.css')\n    ]\n    pdf_attachment = True  # Forces download\n    pdf_filename = 'product_details.pdf'\n\n# urls.py (in your app)\n# urlpatterns = [\n#     path('product/<int:pk>/', ProductDetailView.as_view(), name='product_detail'),\n#     path('product/<int:pk>/pdf/', ProductPDFView.as_view(), name='product_pdf'),\n# ]\n\n# products/product_detail.html (example template)\n# In your template directory:\n# <!DOCTYPE html>\n# <html>\n# <head>\n#     <title>{{ product.name }} PDF</title>\n#     <style>\n#         @page { size: A4; margin: 2cm; }\n#         body { font-family: sans-serif; }\n#         h1 { color: #333; }\n#         .price { color: green; font-weight: bold; }\n#     </style>\n#     <link rel=\"stylesheet\" type=\"text/css\" href=\"{{ STATIC_URL }}css/pdf_styles.css\">\n# </head>\n# <body>\n#     <h1>{{ product.name }}</h1>\n#     <p>{{ product.description }}</p>\n#     <p class=\"price\">Price: ${{ product.price }}</p>\n# </body>\n# </html>\n\n# settings.py (important for static files)\n# STATIC_URL = '/static/'\n# STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')\n","lang":"python","description":"This quickstart demonstrates how to create a basic PDF view for a Django model using `django-weasyprint`. It defines a `Product` model, a `ProductDetailView` for regular HTML display, and a `ProductPDFView` that extends it with `WeasyTemplateResponseMixin` to render the same content as a PDF. Ensure `STATIC_ROOT` and `STATIC_URL` are configured in your Django settings for CSS to be applied correctly, and that WeasyPrint's system dependencies are installed."},"warnings":[{"fix":"Update custom URL fetchers to implement the new `WeasyPrint.urlfetcher.URLFetcher` API and use `from django_weasyprint.urlfetcher import DjangoURLFetcher`.","message":"Version 2.5.0 replaced the `django_url_fetcher` function with a `DjangoURLFetcher` class to align with WeasyPrint 68's URLFetcher API. Existing custom URL fetcher implementations using the old function signature will break.","severity":"breaking","affected_versions":"2.5.0 and later"},{"fix":"Ensure your project uses Python >= 3.10 and WeasyPrint >= 68. Upgrade WeasyPrint if necessary (e.g., `pip install -U WeasyPrint`).","message":"Version 2.5.0 dropped support for WeasyPrint versions older than 68 and Python versions 3.8 and 3.9.","severity":"breaking","affected_versions":"2.5.0 and later"},{"fix":"Upgrade WeasyPrint to version 53.0 or higher. If PNG output is required, consider using an older `django-weasyprint` 1.x release (which uses WeasyPrint/Cairo) or an alternative library for PNG generation.","message":"Version 2.0.0 required WeasyPrint >= 53.0 and removed `PNGView` and `CONTENT_TYPE_*` constants. This means direct PNG output is no longer supported through `django-weasyprint`.","severity":"breaking","affected_versions":"2.0.0 and later"},{"fix":"Refer to the official WeasyPrint installation documentation (e.g., `https://weasyprint.org/docs/install/`) for detailed, OS-specific instructions on installing these system dependencies (e.g., using Homebrew on macOS, `apt` on Ubuntu, or MSYS2/GTK+ runtime on Windows).","message":"WeasyPrint, the underlying rendering engine, requires external system libraries (like Pango, Cairo, and their GTK+ dependencies) to be installed on the operating system, not just via pip. This is a common source of installation issues, especially on Windows or macOS.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Set `pdf_baseurl` in your `WeasyTemplateResponseMixin` or `WeasyTemplateResponse` to `request.build_absolute_uri('/')` to resolve relative URLs. For static files, ensure `STATIC_URL` is correctly configured and accessible, or implement a `DjangoURLFetcher` subclass to resolve them from disk.","message":"Images and CSS stylesheets referenced with relative paths or Django's static/media URLs might not render in the generated PDF unless the `base_url` is correctly configured or a custom URL fetcher is used. WeasyPrint often requires absolute paths or URLs.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Follow the official WeasyPrint installation guide for your operating system to install the necessary system dependencies (e.g., GTK+ runtime on Windows, Homebrew for macOS, `apt` packages on Linux). Ensure their paths are correctly set in system environment variables if required.","cause":"WeasyPrint depends on system-level libraries like Cairo and Pango which are not installed via Python's pip. This error typically occurs on Windows, macOS, or Linux if these graphical dependencies are missing or incorrectly configured.","error":"OSError: dlopen() failed to load a library: cairo / cairo-2"},{"fix":"Install `fontconfig` system packages (e.g., `fontconfig` on Linux). On Windows, ensure GTK+ runtime is installed and its `etc/fonts` directory is accessible, or manually configure a `fonts.conf` file and set the `FONTCONFIG_PATH` environment variable.","cause":"WeasyPrint uses Fontconfig to manage fonts. This error indicates that Fontconfig cannot find its configuration file, often due to missing or improperly configured system font packages or environment variables, especially in headless environments or on Windows.","error":"Fontconfig error: Cannot load default config file"},{"fix":"Replace calls to `django_url_fetcher` with an instance of `DjangoURLFetcher` or a custom class that implements the `WeasyPrint.urlfetcher.URLFetcher` API. Import it using `from django_weasyprint.urlfetcher import DjangoURLFetcher`.","cause":"Attempting to use the old `django_url_fetcher` function after upgrading `django-weasyprint` to version 2.5.0 or later. This function was removed and replaced by a class.","error":"NameError: name 'django_url_fetcher' is not defined"},{"fix":"Set `pdf_baseurl = request.build_absolute_uri('/')` in your `WeasyTemplateResponseMixin` to ensure relative URLs are resolved correctly. For Django static files, ensure `STATIC_URL` is properly configured, `STATIC_ROOT` is collected, and consider implementing a custom `DjangoURLFetcher` if static files are not served via HTTP.","cause":"WeasyPrint is unable to resolve the URLs for static assets (images, stylesheets) referenced in your HTML template. This often happens because relative URLs or Django's static URL patterns are not correctly resolved to absolute paths or accessible URLs during PDF generation.","error":"PDF output not showing images or CSS styles"}]}