· 8 min di lettura
Generare PDF dinamici in Python / Django con JSON
Separa il layout dalla logica Django: invia il JSON dell’ordine a QuartzAPI e restituisci il PDF — senza ReportLab né dipendenze C di WeasyPrint.
In ambienti Python, generare PDF con strumenti come ReportLab significa scrivere codice procedurale per posizionamento, font e interruzioni di riga. Alternative come WeasyPrint richiedono librerie C di sistema (Cairo, Pango) che complicano Docker e il setup dei server.
Con QuartzAPI gli sviluppatori Python separano del tutto il layout dalla logica di business: Django prepara un dizionario JSON; il Visual Builder gestisce il template PDF.
Prerequisiti
- Python 3.8+
- Libreria
requests(pip install requests) - Django 3.2+ / 4.x / 5.x
- Account QuartzAPI, API key e codice template (es.
ORDER_SUMMARY)
Fase 1: utility wrapper API
Crea un modulo (pdf_generator.py) nella tua app Django.
Chiama generate-document, poi scarica i byte del PDF
(la prima risposta è JSON con documentId / downloadUrl).
# utils/pdf_generator.py
import requests
from django.conf import settings
QUARTZ_GENERATE_URL = (
"https://backend.quartzapi.com/index.php?r=api/v1-jobs/generate-document"
)
QUARTZ_DOWNLOAD_URL = (
"https://backend.quartzapi.com/index.php?r=api/v1-documents/download"
)
class PDFGenerationError(Exception):
"""Eccezione custom per errori di generazione PDF."""
pass
def render_pdf_from_template(template_code: str, data: dict) -> bytes:
"""
Invia i dati a QuartzAPI e restituisce i byte PDF grezzi.
"""
headers = {
"Authorization": f"Bearer {settings.QUARTZ_API_KEY}",
"Content-Type": "application/json",
}
payload = {
"templateCode": template_code,
"outputFormat": "pdf",
"data": data,
}
try:
generate = requests.post(
QUARTZ_GENERATE_URL,
json=payload,
headers=headers,
timeout=30,
)
generate.raise_for_status()
body = generate.json()
result = body.get("result") or {}
document_id = result.get("documentId")
download_url = result.get("downloadUrl") or (
f"{QUARTZ_DOWNLOAD_URL}&uid={document_id}"
)
pdf = requests.get(
download_url,
headers={"Authorization": f"Bearer {settings.QUARTZ_API_KEY}"},
timeout=30,
)
pdf.raise_for_status()
return pdf.content
except requests.exceptions.RequestException as e:
raise PDFGenerationError(f"Failed to generate PDF: {str(e)}") from e
Aggiungi la API key in settings.py (in produzione preferisci variabili d’ambiente):
# settings.py
import os
QUARTZ_API_KEY = os.environ.get("QUARTZ_API_KEY", "")
Fase 2: view Django
Una view che carica i model, forma il JSON (in genere sotto master /
master.items) e restituisce un HttpResponse con
application/pdf.
# views.py
from django.http import HttpResponse
from django.views import View
from .utils.pdf_generator import render_pdf_from_template, PDFGenerationError
class ExportOrderPDFView(View):
def get(self, request, order_id):
# 1. Prepara il JSON (in produzione: Order.objects.get(pk=order_id))
order_payload = {
"master": {
"order_id": f"ORD-{order_id}",
"status": "PAID",
"currency": "EUR",
"shipping_address": "123 Tech Street, Milan, Italy",
"total_amount": 199.00,
"items": [
{
"sku": "SDK-01",
"name": "REST API License",
"qty": 1,
"price": 99.00,
},
{
"sku": "SUP-02",
"name": "Priority Support Ticket",
"qty": 2,
"price": 50.00,
},
],
}
}
# 2. Genera i byte PDF via API
try:
pdf_bytes = render_pdf_from_template("ORDER_SUMMARY", order_payload)
except PDFGenerationError as err:
return HttpResponse(str(err), status=500)
# 3. Stream del PDF al browser
response = HttpResponse(pdf_bytes, content_type="application/pdf")
response["Content-Disposition"] = (
f'attachment; filename="order_{order_id}.pdf"'
)
return response
Allinea i nomi campo ai binding del template. Approfondimento sul pattern JSON→PDF: generare fatture PDF da JSON.
Fase 3: routing URL
Collega la view in urls.py dell’app:
# urls.py
from django.urls import path
from .views import ExportOrderPDFView
urlpatterns = [
path(
"orders/<int:order_id>/pdf/",
ExportOrderPDFView.as_view(),
name="export_order_pdf",
),
]
Riepilogo
Con questo pattern l’app Django resta libera da dipendenze C di sistema come Cairo o Pango, i container restano leggeri e i template PDF si aggiornano visivamente senza riavviare i worker WSGI/ASGI.
| Approccio | Codice di layout | Ops / Docker |
|---|---|---|
| ReportLab | X/Y procedurale in Python | Pure Python, ma layout nel repo |
| WeasyPrint | HTML/CSS + librerie di sistema | Cairo, Pango, font nell’immagine |
| QuartzAPI | Visual Builder cloud | Solo requests |
Conclusioni
Tratta la generazione PDF come integrazione HTTP, non come sottosistema grafico dentro Django. Modelli e serializer restano in Python; tipografia e salti pagina restano su QuartzAPI.
Pronto a togliere ReportLab / WeasyPrint?
Registrati alla Beta QuartzAPI, crea un template ordine e collega
render_pdf_from_template alla view di export.
Snippet pronti
- Generate:
POST https://backend.quartzapi.com/index.php?r=api/v1-jobs/generate-documentcontemplateCode+data. - Auth:
Authorization: Bearer {settings.QUARTZ_API_KEY}. - Download:
result.downloadUrloppureGET …/v1-documents/download&uid=…. - Docs: Documentazione Web API.