Rendral

Stack · Django

Generate PDFs in Django

Django already renders HTML beautifully — templates, context, your CSS. The painful part is turning that into a PDF. WeasyPrint drags in Cairo, Pango and GDK-Pixbuf; xhtml2pdf silently ignores modern CSS; wkhtmltopdf is archived and carries an unpatched CVE.

Skip all of it. Call render_to_string() exactly as you already do, POST the result, and stream the PDF straight back through HttpResponse. Your Dockerfile stays a Python image with no system packages bolted on.

01Call it from Django

render.py
# views.py
import requests
from django.conf import settings
from django.http import HttpResponse
from django.template.loader import render_to_string

def invoice_pdf(request, pk):
    html = render_to_string("invoices/show.html", {"invoice": get_invoice(pk)})

    res = requests.post(
        "https://rendral.com/api/v1/pdf",
        headers={"Authorization": "Bearer " + settings.RENDRAL_API_KEY},
        json={"html": html, "options": {"format": "A4", "pageNumbers": True}},
        timeout=60,
    )
    res.raise_for_status()

    return HttpResponse(res.content, content_type="application/pdf")

Frequently asked

Do I have to change my templates?

No. Send whatever render_to_string() already produces. It renders on current headless Chrome, so grid, flexbox and web fonts behave exactly as they do in a browser.

How do static files and images resolve?

Relative URLs have no origin once the HTML leaves your server, so use absolute https:// URLs for images and CSS, or inline them as data URIs. request.build_absolute_uri() is the usual fix.

Should this run in the request cycle?

For a single document it's fine — a render takes a second or two. For bulk jobs, call it from Celery, or send async: true and receive a webhook when the document is ready.

What about WeasyPrint?

WeasyPrint is a capable pure-Python renderer, but it implements its own CSS subset and needs native libraries installed and patched. This runs the same engine as Chrome, with nothing on your image.

Related

Start rendering in minutes.

A free tier, five endpoints, and SDKs for Node and Python.