Library comparison summary to generate PDF with Python

Purpose of this article

When outputting the quotation in PDF, I tried to identify the merits of the related library. The purpose of this article is to present the implementation method and output in the library so that they can be compared.

This article lists and compares the PDF output libraries of the two methods. The method and various libraries are as follows.

--Export HTML to PDF - django-wkhtmltopdf - django_xhtml2pdf - WeasyPrint --What generates PDF from code - reportlab

We also pay attention to the following points regarding comparison.

--Ease of use of the library -Is it easy to use? -Does the code become complicated? -Is the operation heavy? -Is it necessary to install software separately to make it work?

--Maintainability -Is it easy to maintain? --Library update frequency -Is the quality of the output PDF not a problem? -Is there a lot of information on the net?

TL;DR.

I will leave a personal subjective comparison.

Library name ease of use Degree of freedom Maintainability Remarks
django-wkhtmltopdf
django_xhtml2pdf ×
WeasyPrint
reportlab ×

HTML to PDF django-wkhtmltopdf

Documentation django-wkhtmltopdf 3.2.0 documentation

This is a library that wraps wkhtmltopdf, which appears at the top of the search when you search with Python PDF by Google search, for django. It supports Django's class-based view and is very easy to deploy. The generated PDF is also output cleanly by default. However, since it is necessary to install software separately, it seems that it will be difficult to install it on App Engine (verification required).

Installation method

$ pipenv install django-wkhtmltopdf

Software installation is required separately from wkhtmltopdf.

SampleCode

from wkhtmltopdf.views import PDFTemplateView

class PdfSampleView(PDFTemplateView):
    filename = 'my_psdf.pdf'    
    template_name = "pdf_sample/sample.html"

Generated PDF

django_xhtml2pdf

A library that wraps the library django_xhtml2pdf that converts HTML to PDF with Python for Django. A mixin for class-based views is provided and easy to use. In addition, decorators are supported as standard. However, there are few documents and few options. Also, probably because the interpretation of CSS is unique, it is output with a structure different from normal HTML.

xhtml2pdf / django-xhtml2pdf

Installation method

$ pipenv install django_xhtml2pdf

SampleCode

from django_xhtml2pdf.views import PdfMixin

class Xhtml2pdfSampleView_(PdfMixin, TemplateView):
    template_name = "pdf_sample/sample.html"
    

Generated PDF

WeasyPrint

PDF generation tools and libraries close to wkhtmltopdf. The documentation is extensive. Although it is not as good as wkhtmltopdf, it outputs a higher quality PDF than xhtml. There is little difference in the output with HTML compared to xhtml. However, looking at the installation documentation, it seems difficult for App Engine because it needs to be installed separately from the package (requires investigation).

Install | WeasyPrint Documentation

WeasyPrint — WeasyPrint 51 documentation

SampleCode

from weasyprint import HTML, CS
from django.http import HttpResponse
from django.template.loader import get_templat

class WeasyPrintView(TemplateView):
    template_name = 'pdf_sample/sample.html'

    def get(self, request, *args, **kwargs):

        html_template = get_template('pdf_sample/sample.html')
        context = super().get_context_data(**kwargs)

        html_str = html_template.render(context)  
        pdf_file = HTML(string=html_str, base_url=request.build_absolute_uri()).write_pdf(
        )

        response = HttpResponse(pdf_file, content_type='application/pdf')
        response['Content-Disposition'] = 'filename="fuga.pdf"'

        return response

Generated PDF

HardCodePDF

reportlab

It is a library that is generated by actually specifying the layout on the Python code. It is inevitably long because it happens on the code including the style. PDF generation can be executed without any problem. Also, since all data can be inserted in code, the degree of freedom of implementation is very high. Since there are a lot of options and documents, it is possible to create a set of books.

ReportLab - Content to PDF Solutions

Installation method

$ pipenv install reportlab

SampleCode

from django.views.generic import TemplateView
from django.http import HttpResponse

from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib.pagesizes import A4, portrait
from reportlab.platypus import Table, TableStyle
from reportlab.lib.units import mm
from reportlab.lib import colors

class ReportlabView(TemplateView):
    template_name = 'pdf_sample/sample.html'

    def get(self, request, *args, **kwargs):

        response = HttpResponse(status=200, content_type='application/pdf')
        response['Content-Disposition'] = 'filename="example.pdf"'
        # response['Content-Disposition'] = 'attachment; filename="example.pdf"'

        self._create_pdf(response)
        return response

    def _create_pdf(self, response):
        #Set a Gothic font that can use Japanese
        font_name = 'HeiseiKakuGo-W5'
        pdfmetrics.registerFont(UnicodeCIDFont(font_name))

        #Make A4 portrait pdf
        size = portrait(A4)

        #Create a place to draw pdf: The origin of pdf is in the upper left(bottomup=False)
        pdf_canvas = canvas.Canvas(response)
        #header
        font_size = 24  #font size
        pdf_canvas.setFont("HeiseiKakuGo-W5", font_size)
        pdf_canvas.drawString(93 * mm, 770, "Quotation")
        font_size = 10
        pdf_canvas.setFont("HeiseiKakuGo-W5", font_size)
        pdf_canvas.drawString(
            150 * mm, 813, f"Estimated issue date: "
        )
        pdf_canvas.drawString(
            150 * mm,
            800,
            "xxxxxxxxxxx-xxxxxxxxxx",
        )

        # (4)Company name
        data = [
            [f"Hogehoge company", ""],
            ["Project Title", "Hogehoge project"],
            ["Estimated validity period: 30 days from the issue date", ""],
        ]

        table = Table(data, colWidths=(15 * mm, 80 * mm), rowHeights=(7 * mm))
        table.setStyle(
            TableStyle(
                [
                    ("FONT", (0, 0), (-1, -1), "HeiseiKakuGo-W5", 12),
                    ("LINEABOVE", (0, 1), (-1, -1), 1, colors.black),
                    ("VALIGN", (0, 0), (1, -1), "MIDDLE"),
                    ("VALIGN", (0, 1), (0, -1), "TOP"),
                ]
            )
        )
        table.wrapOn(pdf_canvas, 20 * mm, 248 * mm)
        table.drawOn(pdf_canvas, 20 * mm, 248 * mm)



        pdf_canvas.drawString(20 * mm, 238 * mm, "We will quote as follows")
        # (4)Company name
        data = [
            ["Total amount (including consumption tax)", f"1000 yen"],
        ]

        table = Table(data, colWidths=(50 * mm, 60 * mm), rowHeights=(7 * mm))
        table.setStyle(
            TableStyle(
                [
                    ("FONT", (0, 0), (1, 2), "HeiseiKakuGo-W5", 10),
                    ("BOX", (0, 0), (2, 3), 1, colors.black),
                    ("INNERGRID", (0, 0), (1, -1), 1, colors.black),
                    ("VALIGN", (0, 0), (1, 2), "MIDDLE"),
                    ("ALIGN", (1, 0), (-1, -1), "RIGHT"),
                ]
            )
        )
        table.wrapOn(
            pdf_canvas,
            20 * mm,
            218 * mm,
        )
        table.drawOn(
            pdf_canvas,
            20 * mm,
            218 * mm,
        )

        #Item
        data = [["Contents", "Start month", "End month", "unit price", "quantity", "Amount of money"]]

        for idx in range(13):
            data.append([" ", " ", " ", " ", " ", ""])

        data.append([" ", " ", " ", "total", "", f"{1000:,}"])
        data.append([" ", " ", " ", "consumption tax", "", f"{1000 * 0.10:,.0f}"])
        data.append([" ", " ", " ", "Total amount including tax", "", f"{1000 * 1.10:,.0f}"])
        data.append(
            [" ", " ", " ", "", "", ""],
        )

        table = Table(
            data,
            colWidths=(70 * mm, 25 * mm, 25 * mm, 20 * mm, 20 * mm, 20 * mm),
            rowHeights=6 * mm,
        )
        table.setStyle(
            TableStyle(
                [
                    ("FONT", (0, 0), (-1, -1), "HeiseiKakuGo-W5", 8),
                    ("BOX", (0, 0), (-1, 13), 1, colors.black),
                    ("INNERGRID", (0, 0), (-1, 13), 1, colors.black),
                    ("LINEABOVE", (3, 11), (-1, 18), 1, colors.black),
                    ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
                    ("ALIGN", (1, 0), (-1, -1), "RIGHT"),
                ]
            )
        )
        table.wrapOn(pdf_canvas, 17 * mm, 100 * mm)
        table.drawOn(pdf_canvas, 17 * mm, 100 * mm)

        pdf_canvas.drawString(17 * mm, 100 * mm, "<Remarks>")

        table = Table(
            [[""]],
            colWidths=(180 * mm),
            rowHeights=90 * mm,
        )

        table.setStyle(
            TableStyle(
                [
                    ("FONT", (0, 0), (-1, -1), "HeiseiKakuGo-W5", 8),
                    ("BOX", (0, 0), (-1, -1), 1, colors.black),
                    ("INNERGRID", (0, 0), (-1, -1), 1, colors.black),
                    ("VALIGN", (0, 0), (-1, -1), "TOP"),
                ]
            )
        )
        table.wrapOn(pdf_canvas, 17 * mm, 5 * mm)
        table.drawOn(pdf_canvas, 17 * mm, 5 * mm)
        pdf_canvas.showPage()

        #Export pdf
        pdf_canvas.save()
        


Generated PDF generation

reference

Create resume format PDF with python + reportlab-Qiita python 2.7 - HTML to PDF on Google AppEngine - Stack Overflow

Recommended Posts

Library comparison summary to generate PDF with Python
Convert PDF to image (JPEG / PNG) with Python
Try to automatically generate Python documents with Sphinx
Convert the image in .zip to PDF with Python
I tried to automatically generate a password with Python3
Try to automate pdf format report creation with Python
Connect to BigQuery with Python
Generate XML (RSS) with Python
Connect to Wikipedia with Python
Post to slack with Python 3
Integrate PDF files with Python
Switch python to 2.7 with alternatives
Write to csv with Python
[AWS] Try adding Python library to Layer with SAM + Lambda (Python)
Probably the easiest way to create a pdf with Python3
Experiment to make a self-catering PDF for Kindle with Python
20200329_Introduction to Data Analysis with Python Second Edition Personal Summary
Convert images to sepia toning with PIL (Python Imaging Library)
[Road to intermediate Python] Enables comparison operations with original classes
Python: How to use async with
Link to get started with python
Introduction to Python Numerical Library NumPy
Convert markdown to PDF in Python
[Python] Write to csv file with Python
Create folders from '01' to '12' with python
Nice to meet you with python
Try to operate Facebook with Python
How to use Requests (Python Library)
Output to csv file with Python
Convert list to DataFrame with python
MP3 to WAV conversion with Python
[python] Copy script to generate copy log
To do tail recursion with Python2
How to get started with Python
[Python] How to import the library
What to do with PYTHON release?
Unable to install Python with pyenv
How to use FTP with Python
[Python] Generate a password with Slackbot
[Hyperledger Iroha] Query with Python library
How to calculate date with python
[Introduction to Udemy Python 3 + Application] Summary
Convert PDF to image with ImageMagick
Easily post to twitter with Python 3
I want to debug with Python
Generate a Python library download badge
Generate error correction code to restore data corruption with zfec library
I made a library to easily read config files with Python
Convert files written in python etc. to pdf with syntax highlighting
[Python] Summary of how to use pandas
Python Summary
Try logging in to qiita with Python
Change Python 64bit environment to 32bit environment with Anaconda
English speech recognition with python [speech to text]
Convert memo at once with Python 2to3
HTML email with image to send with python
Memo to ask for KPI with python
Python to remember only with hello, worlds
Output color characters to pretty with python
Generate Japanese test data with Python faker
Convert from PDF to CSV with pdfplumber