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).
$ 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"
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.
$ pipenv install django_xhtml2pdf
SampleCode
from django_xhtml2pdf.views import PdfMixin
class Xhtml2pdfSampleView_(PdfMixin, TemplateView):
template_name = "pdf_sample/sample.html"
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
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
$ 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()
Create resume format PDF with python + reportlab-Qiita python 2.7 - HTML to PDF on Google AppEngine - Stack Overflow
Recommended Posts