Django-de

Django Dokumentation

Ausgabe von PDFs mit Django

Diese Dokumentation gilt für Djangos Entwicklerversion, die zum Teil erhebliche Unterschiede zur letzten veröffentlichen Version aufweist.

Dieses Dokument erklärt, wie man PDF-Dateien dynamisch mit Hilfe von Django-Views erzeugt. Ermöglicht wird das Erstellen von PDFs durch die ausgezeichnete Open-Source-Bibliothek ReportLab.

Der Vorteil des dynamischen Erstellens von PDF-Dateien ist, dass angepasste PDFs für unterschiedlichste Anforderungen — z.B. für verschiedene Benutzer oder verschiedene Inhalte — generiert werden können.

Beispielsweise wurde Django auf kusports.com verwendet, um angepasste, druckfreundliche NCAA Turnierspielpläne als PDF-Dateien für Teilnehmer an einem “March Madness”-Wettkampf zu erzeugen.

Installiere ReportLab

Lade die ReportLab-Bibliothek von http://www.reportlab.org/downloads.html herunter und installiere sie. Die Bedienungsanleitung (nicht nur zufällig eine PDF-Datei) erklärt die Vorgangsweise für die Installation.

Teste deine Installation, indem du ReportLab im interaktiven Python-Interpreter importierst:

>>> import reportlab

Wenn dieses Kommando keine Fehler verursacht, war die Installation erfolgreich.

Schreibe deine View

Entscheidend für das dynamische Erstellen von PDFs mit Django ist die ReportLab API, die mit dateiähnlichen Objekte arbeitet, und Djangos HttpResponse-Objekte sind dateiähnliche Objekte.

Beachte

Für weitere Informationen zu HttpResponse-Objekten siehe Request- und Response-Objekte.

Hier ein “Hello World” Beispiel:

from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Erzeuge das HttpResponse Objekt mit den passenden PDF-Headern.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

    # Erzeuge das PDF-Objekt mit dem Response Objekt als seiner "Datei".
    p = canvas.Canvas(response)

    # Zeichne auf dem PDF. Hier geschieht die eigentliche PDF-Generierung.
    # Siehe die ReportLab Dokumentation für die gesamte Funktionalität.
    p.drawString(100, 100, "Hello world.")

    # Schließ das PDF-Objekt, und fertig.
    p.showPage()
    p.save()
    return response

Der Code und die Kommentare sollten selbsterklärend sein, aber einige Dinge verdienen eine kurze Erwähnung:

  • Das Response-Objekt erhält einen speziellen Mimetype, application/pdf. Dieses informiert den Browser, dass es sich bei dem Dokument um eine PDF-Datei handelt, und nicht um HTML. Wenn du das weglässt, wird das Dokument wahrscheinlich als HTML interpretiert und im Browserfenster als “Zeichenmüll” dargestellt werden.

  • Das Response-Objekt erhält einen zusätzlichen Content-Disposition Header, der den Namen der PDF-Datei enthält. Dieser Dateiname kann frei gewählt werden. Er wird vom Browser im “Speichern als…” Dialog etc. verwendet werden.

  • Der Content-Disposition-Header beginnt in unserem Beispiel mit 'attachment; '. Das zwingt den Webbrowser dazu, einen Dialog zu öffnen, um zu bestätigen, wie mit der Datei verfahren werden soll; auch wenn eine Standardeinstellung auf dem Rechner getätigt ist. Wenn du 'attachment; ' weglässt, wird der Browser die PDF-Datei entsprechend ihrer Standardeinstellung für diesen Dateityp behandeln. So sollte der Code aussehen:

    response['Content-Disposition'] = 'filename=somefilename.pdf'
    
  • Das Anhängen an die ReportLab-API ist simpel: Übergib einfach response als erstes Argument an canvas.Canvas. Die Canvas Klasse erwartet ein dateiähnliches Objekt, und das trifft auf HttpResponse zu.

  • Beachte, dass alle nachfolgenden Methoden für die PDF-Erzeugung mit dem PDF-Objekt (in diesem Fall p) aufgerufen werden — nicht mit response.

  • Abschließend ist es noch wichtig, showPage() und save() mit dem PDF-Objekt aufzurufen.

Komplexe PDFs

Wenn du mit ReportLab ein komplexes PDF-Dokument erzeugen willst, ziehe bitte in Erwägung, die cStringIO Bibliothek als temporären Platzhalter für deine PDF-Datei zu verwenden. Die cStringIO Bibliothekt stellt ein Interface zu einem dateiähnlichen Objekt bereit, das besonders effizient ist. Nachfolgend findest du das “Hello World” Beispiel von oben, das unter Verwendung von cStriongIO umgeschrieben wurde:

from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Erzeuge das HttpResponse Objekt mit den passenden PDF-Headern.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

    buffer = StringIO()

    # Erzeuge das PDF-Objekt, mit dem StringIO Objekt als seiner "Datei".
    p = canvas.Canvas(buffer)

    # Zeichne auf dem PDF. Hier geschieht die eigentliche PDF-Generierung.
    # Siehe die ReportLab Dokumentation für die gesamte Funktionalität.
    p.drawString(100, 100, "Hello world.")

    # Schließe das PDF-Objekt.
    p.showPage()
    p.save()

    # Hol den Inhalt des StringIO Buffers und schreib ihn ins Response Objekt.
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

Weiterführende Ressourcen

  • PDFlib ist eine weitere Bibliothek zur Erzeugung von PDFs, die über Python Anbindung verfügt. Um sie unter Django zu benutzen, verwende einfach die gleichen Konzepte wie in diesem Artikel.
  • HTMLdoc ist ein Kommandozeilen-Script, das HTML in PDF konvertieren kann. Es hat kein Python-Interface, aber du kannst es über system oder popen aufrufen und die Ausgabe in Python auslesen.
  • forge_fdf in Python ist eine Bibliothek, die PDF-Formulare ausfüllt.