Reportlab is awesome. It took me about a day or two to figure out how to programmatically produce quite complex PDF-files. I installed Reportlab into my venv and then I created a folder inside my project called pdf_generator. I created a file called factory.py. I have a method in there which takes a user, a month, a year and a project. Users will enter their work time into the system and then the system will produce a printable time sheet in the form of a PDF, save it and return the path to the file. Here’s the code I wrote. This will give you an example of how to create a basic document and put a table into it that is filled with data. I hope this will help you to get started.
import datetime
import os
from ahub import settings as s
from django.utils.timezone import now
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Image
from reportlab.lib.pagesizes import A4, cm
from reportlab.lib import colors
from time_manager.entry.models import Entry
class PDFGenerator(object):
""" This class contains factory methods for creating PDF files. The methods should create and store the PDF and
return the file path. """
@staticmethod
def get_directory():
""" Build the path for the directory to store in. Takes the username as argument. """
directory = os.path.join(s.MEDIA_ROOT, 'time_manager', 'pdf', 'temp')
# Create directory if it doesn't exist yet.
if not os.path.exists(directory):
os.makedirs(directory)
return directory
@staticmethod
def time_sheet(user, year, month, project):
""" Creates a time sheet with the work time a user entered for a certain project. """
# Store the PDF in a sub folder named after the username with the following filename format:
# YYYYMMDD_ZE_NameConsultant_Project_MMYY
date = datetime.date(year=year, month=month, day=1)
filename = now().strftime('%Y%m%d') + '_ZE_' + user.last_name + user.first_name + '_' + project.customer + \
'_' + date.strftime('%m%y') + '.pdf'
directory = PDFGenerator.get_directory()
store_path = os.path.join(directory, filename)
# Initiate doc.
doc = SimpleDocTemplate(store_path, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18)
# Build header.
header_text = 'Stundenzettel\n' + user.last_name + ', ' + user.first_name + '\n' + project.customer + '\n' + \
date.strftime('%B %Y')
header_logo = Image(os.path.join(s.BASE_DIR, 'pdf_generator', 'files', 'logo_auticon.jpg'))
header_table = Table([(header_text, header_logo,)], colWidths=[8*cm], rowHeights=[5*cm])
header_table.setStyle(TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP'),
('ALIGN', (0, 0), (0, 0), 'LEFT'),
('ALIGN', (1, 0), (1, 0), 'RIGHT'),
]))
# Build content table.
content_table = Table(data=Entry.render_entries_for_pdf(user, year, month, project))
content_table.setStyle(TableStyle([('INNERGRID', (0, 0), (-1, -1), 0.25, colors.gray),
('ALIGN', (3, 0), (-1, -1), 'RIGHT'),
]))
# Build footer.
footer_top_row = ('', '', '', '', '')
footer_bot_row = ('Ort/Datum', 'Kunde', '', 'Ort/Datum', 'Consultant', )
footer_table = Table([footer_top_row, footer_bot_row], colWidths=[3*cm, 3*cm, 4*cm, 3*cm, 3*cm], rowHeights=[2*cm, 0.5*cm])
footer_table.setStyle(TableStyle([('INNERGRID', (0, 0), (0, 1), 0.25, colors.gray),
('INNERGRID', (1, 0), (1, 1), 0.25, colors.gray),
('INNERGRID', (3, 0), (3, 1), 0.25, colors.gray),
('INNERGRID', (4, 0), (4, 1), 0.25, colors.gray),
]))
# Build layout table.
data = [(header_table, ), (content_table, ), (footer_table, )]
layout_table = Table(data)
layout_table.setStyle(TableStyle([('ALIGN', (0, 0), (-1, -1), 'CENTER')]))
doc.build([layout_table])
return store_path