Εξάγοντας αρχεία PDF με το Django

Αυτό το άρθρο εξηγεί πως να εξάγετε αρχεία PDF, δυναμικά, χρησιμοποιώντας τα Django views. Αυτό είναι εφικτό, με τη χρήση της εξαιρετικής, ανοιχτού λογισμικου PDF βιβλιοθήκης της Python, ReportLab.

Το πλεονέκτημα της παραγωγής δυναμικών αρχείων PDF είναι ότι μπορείτε να δημιουργείτε παραμετροποιήσιμα PDFs για διαφορετικούς σκοπούς – πχ, για διαφορετικούς χρήστες ή διαφορετικά κομμάτια δεδομένων.

Για παράδειγμα, το Django χρησιμοποιήθηκε στο kusports.com για να παράγει παραμετροποιήσιμα, φιλικά προς εκτύπωση αποτελέσματα αγώνων μπάσκετ (NCAA tournament brackets), ως αρχεία PDF, για αυτούς που συμμετέχουν στον διαγωνισμό March Madness.

Εγκατάσταση της βιβλιοθήκης ReportLab

Η βιβλιοθήκη ReportLab είναι διαθέσιμη στο PyPI. Ένας οδηγός χρήστη (όχι τυχαία, ένα PDF αρχείο) είναι επίσης διαθέσιμο για download. Μπορείτε να εγκαταστήσετε το ReportLab με το pip:

$ pip install reportlab

Ελέγξτε την εγκατάσταση της βιβλιοθήκης κάνοντας την import στο Python interactive shell σας (αν την έχετε εγκαταστήσει globally, τότε σε κονσόλα γράψτε πρώτα python ή python3.x όπου x η έκδοση Python που χρησιμοποιείτε):

>>> import reportlab

Αν αυτό δεν σας εμφανίσει κάποιο σφάλμα, η βιβλιοθήκη έχει εγκατασταθεί επιτυχώς.

Γράψτε το view

Το κλειδί για να παράγετε PDFs δυναμικά με το Django είναι ότι το ReportLab API ενεργεί σε objects που μοιάζουν με αρχεία και τα objects της κλάσης HttpResponse του Django μοιάζουν με αρχεία.

Εδώ φαίνεται το κλασικό παράδειγμα “Hello World”:

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

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

    # Create the PDF object, using the response object as its "file."
    p = canvas.Canvas(response)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()
    return response

Παρόλο που ο κώδικας και τα σχόλια είναι αρκετά επεξηγηματικά, θα πρέπει να αναφέρουμε μερικά πράγματα:

  • Το response παίρνει έναν ειδικό τύπο MIME, application/pdf. Αυτό λέει στους browsers ότι το έγγραφο είναι ένα PDF αρχείο, αντί ένα HTML αρχείο. Αν δεν το προσδιορίσετε, οι browsers θα ερμηνεύσουν την έξοδο ως HTML, που σημαίνει ότι όχι μόνο η έξοδος θα είναι άσχημη αλλά δεν θα καταλαβαίνετε τίποτα!

  • Το response παίρνει ένα επιπλέον header με το όνομα Content-Disposition, ο οποίος περιέχει το όνομα του αρχείου PDF. Το όνομα αυτό είναι αυθαίρετο: Μπορείτε να το ονομάσετε όπως εσείς θέλετε. Θα χρησιμοποιηθεί από τους browsers στο παράθυρο διαλόγου “Αποθήκευση ως...” κλπ.

  • Σε αυτό το παράδειγμα, ο header Content-Disposition ξεκινά με τη λέξη 'attachment; '. Αυτό αναγκάζει τους Web browsers να εμφανίσουν ένα pop-up παράθυρο διαλόγου ρωτώντας τον χρήστη πως να χειριστεί το έγγραφο ακόμη και αν μια προεπιλεγμένη ενέργεια είναι ρυθμισμένη στον browser. Αν το παραλείψετε αυτό, οι browsers θα χειριστούν το PDF χρησιμοποιώντας οποιοδήποτε πρόγραμμα/plugin είναι ρυθμισμένοι να χρησιμοποιούν όταν έρχονται αντιμέτωποι με τέτοιου είδους αρχεία. Ο κώδικας θα φαίνεται κάπως έτσι:

    response['Content-Disposition'] = 'filename="somefilename.pdf"'
    
  • Η επικοινωνία με το ReportLab API είναι εύκολη: Απλώς περάστε το response ως πρώτο όρισμα στην κλάση canvas.Canvas. Η κλάση Canvas περιμένει ένα object που μοιάζει με αρχείο και τα objects της κλάσης HttpResponse ταιριάζουν ακριβώς με την περιγραφή.

  • Σημειώστε ότι όλες οι ακόλουθες μέθοδοι που δημιουργούν PDF, καλούνται πάνω στο PDF object (σε αυτή την περίπτωση, στο p) – όχι πάνω στο response.

  • Στο τέλος είναι σημαντικό να καλέσετε τις μεθόδους showPage() και save() στο PDF object.

Σημείωση

Η βιβλιοθήκη ReportLab δεν είναι ασφαλής από πολλαπλά threads. Μερικοί από τους χρήστες ανέφεραν κάποια περίεργα προβλήματα όταν πολλοί χρήστες είχαν πρόσβαση, ταυτόχρονα, στα Django views που χρησιμοποιούνταν για να παράξουν PDF αρχεία.

Περίπλοκα PDFs

Αν δημιουργείτε ένα περίπλοκο έγγραφο PDF με το ReportLab, σκεφτείτε να χρησιμοποιήσετε τη βιβλιοθήκη io ως ένα προσωρινό μέρος για να κρατάτε το PDF αρχείο σας. Αυτή η βιβλιοθήκη παρέχει ένα interface που μοιάζει με file object το οποίο είναι ιδιαίτερα αποδοτικό. Παρακάτω φαίνεται το παράδειγμα “Hello World” χρησιμοποιώντας, αυτή τη φορά, τη βιβλιοθήκη io:

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

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

    buffer = BytesIO()

    # Create the PDF object, using the BytesIO object as its "file."
    p = canvas.Canvas(buffer)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly.
    p.showPage()
    p.save()

    # Get the value of the BytesIO buffer and write it to the response.
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

Άλλες μορφές τύπου κειμένου

Όπως είδατε, δεν υπάρχει κάτι συγκεκριμένο με το PDF εδώ – μόνο τα κομμάτια που χρησιμοποιούν τη βιβλιοθήκη reportlab. Μπορείτε να χρησιμοποιήσετε κάποια παρόμοια τεχνική για να εξάγετε οποιαδήποτε μορφή τύπου κειμένου, αρκεί να υπάρχει μια Python βιβλιοθήκη που να την υποστηρίζει. Δείτε στο άρθρο Εξάγοντας αρχεία CSV με το Django για ένα άλλο παράδειγμα και μερικές τεχνικές που μπορείτε να χρησιμοποιήσετε όταν παράγετε αρχεία με μορφή τύπου κειμένου.

Δείτε επίσης

Τα Django Packages παρέχουν συγκριτικό πίνακα μεταξύ των πακέτων ο οποίος βοηθά στη δημιουργία PDF αρχείων από το Django.

Back to Top