Well, here’s a fragment of the formation of a fairly large PDF, I hope it helps to catch the direction, here both the tables and custom fonts and the insertion of images, page numbers, then various graphs are formed depending on the parameters that have come:
def conclusion_to_pdf(s_id): tests = SeanceTests.objects.filter(seance=s_id) seances = Seance.objects.select_related().get(id=s_id) filename = seances.profile.account.username + '_results.pdf' response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'filename="%s"' % filename pdfmetrics.registerFont(TTFont('Times', 'times.ttf', 'UTF-8')) pdfmetrics.registerFont(TTFont('Times-Bold', 'timesbd.ttf', 'UTF-8')) pdfmetrics.registerFont(TTFont('Times-Italic', 'timesi.ttf', 'UTF-8')) pdfmetrics.registerFont(TTFont('Times-BoldItalic', 'timesbi.ttf', 'UTF-8')) from reportlab.lib.fonts import addMapping addMapping('Times', 0, 0, 'Times') #normal addMapping('Times', 0, 1, 'Times-Italic') #italic addMapping('Times', 1, 0, 'Times-Bold') #bold addMapping('Times', 1, 1, 'Times-BoldItalic') #italic and bold doc = SimpleDocTemplate(response, pagesize=A4, rightMargin=40, leftMargin=40, topMargin=20, bottomMargin=40, title='Результаты') story = [] styles = getSampleStyleSheet() styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY, fontName='Times', fontSize=11)) styles.add(ParagraphStyle(name='Justify-Bold', alignment=TA_JUSTIFY, fontName='Times-Bold')) bold_style = styles['Justify-Bold'] normal_style = styles['Justify'] doc_title = copy.copy(styles["Heading1"]) doc_title.alignment = TA_CENTER doc_title.fontName = 'Times-Bold' doc_title.fontSize = 16 title = 'Отчет по результатам тестирования' story.append(Paragraph(title, doc_title)) # logo from psycho2.settings import STATIC_PATH logo = STATIC_PATH + '/img/logo.png' im = Image(logo, 70*mm, 30*mm) story.append(im) story.append(Spacer(1, 10)) result_table_style = TableStyle([ ('FONT', (0, 0), (-1, -1), 'Times-Bold', 10), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('GRID', (0, 0), (-1, -1), 0.25, colors.black), ('BACKGROUND', (0, 0), (15, -2), colors.lightgrey), ]) normal_table_style = TableStyle([ ('FONT', (0, 0), (-1, -1), 'Times', 10), ('ALIGN', (0, 0), (0, -1), 'CENTRE'), ('GRID', (0, 0), (-1, -1), 0.25, colors.black), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE') ]) # for u in context['seances']: personal_data = [ [u'ФИО', "%s %s %s" % (seances.profile.account.last_name, seances.profile.account.first_name, seances.profile.account.middle_name)], [u'Год рождения', seances.profile.year], [u'Пол', seances.profile.get_sex_display()], [u'Семейное положение', seances.profile.get_marital_status_display()], [u'Образование', seances.profile.get_education_display()], [u'Профессия', seances.profile.professional_sphere], [u'Дата завершения сеанса', seances.finished_date] ] table = Table(personal_data, rowHeights=15) table.setStyle(TableStyle([ ('FONT', (0, 0), (-1, -1), 'Times', 10), ('ALIGN', (0, 0), (0, -1), 'RIGHT'), ('GRID', (0, 0), (-1, -1), 0.25, colors.black), ])) story.append(table) story.append(Spacer(1, 10)) doc_title.fontSize = 12
... further a lot of things ... well, in the final:
doc.build(story, canvasmaker=PageNumCanvas) return response
Response use at its discretion, or display in the browser, or save to a file and attach to the letter. As for CSV, there are separate utilities in python for building with CSV. For Word, there are also separate packages. What else can you do with ReportLab - generate charts (very diverse) in the form of images. If you use it, I recommend saving it in the svg format; otherwise, if there are Russian fonts in the graphic, there will be many dances with a tambourine.