From 511f21eb4da794d37707fed891ce31737071f8d7 Mon Sep 17 00:00:00 2001 From: alazo Date: Thu, 2 Nov 2017 14:56:11 +0100 Subject: [PATCH] PDF documents --- cms/pdf.py | 145 ++++++++++++++++++++++++++++----------------------- cms/views.py | 21 +++----- 2 files changed, 86 insertions(+), 80 deletions(-) diff --git a/cms/pdf.py b/cms/pdf.py index 3ec6b2e..7485249 100644 --- a/cms/pdf.py +++ b/cms/pdf.py @@ -1,10 +1,8 @@ - import os -from django.http.response import HttpResponse + from django.conf import settings from reportlab.platypus import (SimpleDocTemplate, Spacer, Frame, Paragraph, Preformatted, - PageTemplate, NextPageTemplate, FrameBreak) -from reportlab.platypus import Table, TableStyle, Image + PageTemplate, NextPageTemplate, FrameBreak, Table, TableStyle) from reportlab.lib.pagesizes import A4, landscape from reportlab.lib.units import cm from reportlab.lib.enums import TA_LEFT, TA_CENTER @@ -12,19 +10,19 @@ from reportlab.lib import colors from reportlab.lib.colors import HexColor from reportlab.lib.styles import ParagraphStyle as ps from reportlab.pdfgen import canvas -from reportlab.pdfbase.pdfmetrics import stringWidth -from reportlab.lib.styles import getSampleStyleSheet -style_8_c = ps(name='CORPS', fontName='Helvetica', fontSize=6, alignment=TA_CENTER) style_normal = ps(name='CORPS', fontName='Helvetica', fontSize=9, alignment=TA_LEFT) style_bold = ps(name='CORPS', fontName='Helvetica-Bold', fontSize=10, alignment=TA_LEFT) -style_title = ps(name='CORPS', fontName='Helvetica', fontSize=12, alignment=TA_LEFT) -style_adress = ps(name='CORPS', fontName='Helvetica', fontSize=10, alignment=TA_LEFT, leftIndent=300) LOGO_EPC = os.path.join(settings.MEDIA_ROOT, 'logo_EPC.png') LOGO_ESNE = os.path.join(settings.MEDIA_ROOT, 'logo_ESNE.png') +FILIERE = 'Formation EDS' class NumberedCanvas(canvas.Canvas): + """ + Page number and page count + """ + def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) self._saved_page_states = [] @@ -44,80 +42,91 @@ class NumberedCanvas(canvas.Canvas): def draw_page_number(self, page_count): self.setFont("Helvetica", 7) - self.drawRightString(20*cm, 2*cm, "Page %d de %d" % (self._pageNumber, page_count)) + self.drawString(self._pagesize[0] / 2, 1 * cm, "Page {0} de {1}".format(self._pageNumber, page_count)) class EpcBaseDocTemplate(SimpleDocTemplate): - def __init__(self, filename, titles=['', ''], pagesize=A4): + def __init__(self, filename, title='', pagesize=A4): super().__init__(filename, pagesize=pagesize, _pageBreakQuick=0, lefMargin=1.5 * cm, bottomMargin=1.5 * cm, topMargin=1.5 * cm, rightMargin=1.5 * cm) self.story = [] - self.titles = titles + self.title = title def header(self, canvas, doc): canvas.saveState() canvas.drawImage(LOGO_EPC, doc.leftMargin, doc.height - 0.5 * cm, 5 * cm, 3 * cm, preserveAspectRatio=True) canvas.drawImage(LOGO_ESNE, doc.width - 2 * cm, doc.height - 0.5 * cm, 5 * cm, 3 * cm, preserveAspectRatio=True) - canvas.line(doc.leftMargin, doc.height - 0.5 * cm, doc.width+doc.leftMargin, doc.height - 0.5 * cm) - canvas.drawString(doc.leftMargin, doc.height - 1.1 * cm, self.titles[0]) - canvas.drawRightString(doc.width+doc.leftMargin, doc.height - 1.1 * cm, self.titles[1]) - canvas.line(doc.leftMargin, doc.height - 1.3 * cm, doc.width+doc.leftMargin, doc.height - 1.3 * cm) + canvas.line(doc.leftMargin, doc.height - 0.5 * cm, doc.width + doc.leftMargin, doc.height - 0.5 * cm) + canvas.drawString(doc.leftMargin, doc.height - 1.1 * cm, FILIERE) + canvas.drawRightString(doc.width + doc.leftMargin, doc.height - 1.1 * cm, self.title) + canvas.line(doc.leftMargin, doc.height - 1.3 * cm, doc.width + doc.leftMargin, doc.height - 1.3 * cm) + canvas.restoreState() + + def later_header(self, canvas, doc): + canvas.saveState() + canvas.line(doc.leftMargin, doc.height + 1 * cm, doc.width + doc.leftMargin, doc.height + 1 * cm) + canvas.drawString(doc.leftMargin, doc.height + 0.5 * cm, FILIERE) + canvas.drawRightString(doc.width + doc.leftMargin, doc.height + 0.5 * cm, self.title) + canvas.line(doc.leftMargin, doc.height + 0.2 * cm, doc.width + doc.leftMargin, doc.height + 0.2 * cm) canvas.restoreState() def setNormalTemplatePage(self): first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 4 * cm, - id='small_table', showBoundary=0, leftPadding=0 * cm) + id='first_table', showBoundary=0, leftPadding=0 * cm) later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 2 * cm, - id='large_table', showBoundary=0, leftPadding=0 * cm) + id='later_table', showBoundary=0, leftPadding=0 * cm) + # Page template first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.header) - later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame]) + later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.later_header) self.addPageTemplates([first_page, later_pages]) self.story = [NextPageTemplate(['*', 'LaterPages'])] def setSixSemestreTemplatePage(self): - width = 8 * cm - height = 6.5 * cm + frame_size = (8 * cm, 6.5 * cm,) + w, h = frame_size x = [self.leftMargin, 12 * cm] * 3 - y = [17*cm, 17*cm, 10*cm, 10*cm, 3*cm, 3*cm] - frames = [Frame(x[f], y[f], width=width, height=height, showBoundary=0, leftPadding=0) for - f in range(6)] - frames.append(Frame(self.leftMargin, self.bottomMargin, self.width, 1.5*cm, leftPadding=0)) + y = [17 * cm, 17 * cm, 10 * cm, 10 * cm, 3 * cm, 3 * cm] + frames = [Frame(x[f], y[f], width=w, height=h, showBoundary=0, leftPadding=0) for f in range(6)] + # Frame for total periods + frames.append(Frame(self.leftMargin, self.bottomMargin, self.width, 1.5 * cm, leftPadding=0)) # Page template frame_page = PageTemplate(id='FirstPage', frames=frames, onPage=self.header) self.addPageTemplates(frame_page) -class ModulePdf(EpcBaseDocTemplate): +class ModuleDescriptionPdf(EpcBaseDocTemplate): + """ + PDF for module description + """ def __init__(self, filename): - super().__init__(filename, ['Formation EDS', 'Module de formation'], A4) + super().__init__(filename, 'Module de formation', A4) self.setNormalTemplatePage() def produce(self, module): - str_comp = '' + str_competence = '' for c in module.competence_set.all(): - str_comp += '- {0} ({1})\n'.format(c.nom, c.code) + str_competence += '- {0} ({1})\n'.format(c.nom, c.code) """ if self.request.user.is_authenticated: for sc in c.souscompetence_set.all(): str_comp += ' -- {0}\n'.format(sc.nom) """ - - str_scom = '' + str_sous_competence = '' for c in module.competence_set.all(): for sc in c.souscompetence_set.all(): - str_scom += '- {0} (voir {1})\n'.format(sc.nom, c.code) + str_sous_competence += '- {0} (voir {1})\n'.format(sc.nom, c.code) str_res = '' for c in module.ressource_set.all(): str_res += '- {0}\n'.format(c.nom) - str_obj = '' + str_objectif = '' for c in module.objectif_set.all(): - str_obj += '- {0}\n'.format(c.nom) + str_objectif += '- {0}\n'.format(c.nom) self.story.append(Paragraph(module.__str__(), style_bold)) self.story.append(Spacer(0, 0.5 * cm)) @@ -126,9 +135,9 @@ class ModulePdf(EpcBaseDocTemplate): ['Domaine', module.processus.domaine.__str__()], ['Processus', module.processus.__str__()], ['Situation emblématique', module.situation], - ['Compétences visées', str_comp], - ['Plus-value sur le CFC ASE', str_scom], - ['Objectifs', str_obj], + ['Compétences visées', str_competence], + ['Plus-value sur le CFC ASE', str_sous_competence], + ['Objectifs', str_objectif], ['Didactique', module.didactique], ['Evaluation', module.evaluation], ['Type', '{0}, obligatoire'.format(module.type)], @@ -146,24 +155,29 @@ class ModulePdf(EpcBaseDocTemplate): ] ) - t = Table(formated_data, colWidths=[4*cm, 13*cm]) + t = Table(formated_data, colWidths=[4 * cm, 13 * cm]) t.hAlign = TA_LEFT t.setStyle( - TableStyle([ - ('SIZE', (0, 0), (-1, -1), 7), - ('ALIGN', (0, 0), (-1, -1), 'LEFT'), - ('VALIGN', (0, 0), (-1, -1), 'TOP'), - ('LEFTPADDING', (0, 0), (-1, -1), 0), ] + TableStyle( + [ + ('SIZE', (0, 0), (-1, -1), 7), + ('ALIGN', (0, 0), (-1, -1), 'LEFT'), + ('VALIGN', (0, 0), (-1, -1), 'TOP'), + ('LEFTPADDING', (0, 0), (-1, -1), 0), + ] ) ) self.story.append(t) self.build(self.story, canvasmaker=NumberedCanvas) -class PlanFormationPdf(EpcBaseDocTemplate): +class FormationPlanPdf(EpcBaseDocTemplate): + """ + PDF for formation plan + """ def __init__(self, filename): - super().__init__(filename, ['Formation EDS', 'Plan de formation'], landscape(A4)) + super().__init__(filename, 'Plan de formation', landscape(A4)) self.setNormalTemplatePage() def formating(self, el1='', length=40): @@ -171,7 +185,6 @@ class PlanFormationPdf(EpcBaseDocTemplate): return Preformatted(el1, style_normal, maxLineLength=length) def produce(self, domain, process): - # my_frame = Frame(2*cm, 1*cm, 26*cm, 15*cm, showBoundary=1) data = [ ['Domaines', 'Processus', 'Sem1', 'Sem2', 'Sem3', 'Sem4', 'Sem5', 'Sem6'], [self.formating(domain[0]), self.formating(process[0], 60), 'M01', '', '', '', '', ''], @@ -189,8 +202,9 @@ class PlanFormationPdf(EpcBaseDocTemplate): [self.formating(domain[6]), self.formating(process[9], 60), 'M17_1', '', 'M17_2', '', 'M17_3', ''], [self.formating(domain[7]), self.formating(process[10], 60), 'Macc', '', '', '', '', ''], ] - t = Table(data, colWidths=[7*cm, 9*cm, 1.5*cm, 1.5*cm, 1.5*cm, 1.5*cm, 1.5*cm, 1.5*cm], - spaceBefore=0.5*cm, spaceAfter=1*cm) + t = Table(data, colWidths=[7 * cm, 9 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm], + spaceBefore=0.5 * cm, spaceAfter=1 * cm + ) t.setStyle(TableStyle([ ('SIZE', (0, 0), (-1, -1), 8), ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'), @@ -244,13 +258,16 @@ class PlanFormationPdf(EpcBaseDocTemplate): ])) t.hAlign = TA_LEFT self.story.append(t) - self.build(self.story) + self.build(self.story, canvasmaker=NumberedCanvas) -class PeriodeFormationPdf(EpcBaseDocTemplate): - """Imprime les heures de cours par semestre""" +class PeriodSemesterPdf(EpcBaseDocTemplate): + """ + PDF for periods during semesters + """ + def __init__(self, filename): - super().__init__(filename, ['Filière EDS', 'Périodes de formation'], A4) + super().__init__(filename, 'Périodes de formation', A4) self.setSixSemestreTemplatePage() def produce(self, context): @@ -261,19 +278,17 @@ class PeriodeFormationPdf(EpcBaseDocTemplate): for line in modules: value = getattr(line, 'sem{0}'.format(sem)) data.append([line.nom, '{0} h.'.format(value)]) - t = Table(data, colWidths=[6.5*cm, 1*cm], spaceBefore=0.5*cm, spaceAfter=1*cm, hAlign=TA_LEFT) - t.setStyle(TableStyle( - [ - ('ALIGN', (0, 0), (0, 0), 'LEFT'), - ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), - ('LINEBELOW', (0, 0), (1, 0), 1, colors.black), - ('SIZE', (0, 0), (-1, -1), 9), - ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'), - ] - ) - ) - + t = Table(data, colWidths=[6.5 * cm, 1 * cm], spaceBefore=0.5 * cm, spaceAfter=1 * cm, hAlign=TA_LEFT, + style=[ + ('ALIGN', (0, 0), (0, 0), 'LEFT'), + ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), + ('LINEBELOW', (0, 0), (1, 0), 1, colors.black), + ('SIZE', (0, 0), (-1, -1), 9), + ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'), + ] + ) self.story.append(t) self.story.append(FrameBreak()) + self.story.append(Paragraph('Total de la formation: {0} heures'.format(context['tot']), style_bold)) - self.build(self.story) + self.build(self.story, canvasmaker=NumberedCanvas) diff --git a/cms/views.py b/cms/views.py index 10a2564..c442cd9 100644 --- a/cms/views.py +++ b/cms/views.py @@ -9,9 +9,8 @@ import tempfile from django.views.generic import ListView, TemplateView, DetailView from django.db.models import F, Sum from django.http import HttpResponse -from reportlab.pdfgen import canvas -from cms.pdf import PeriodeFormationPdf, ModulePdf, PlanFormationPdf +from cms.pdf import PeriodSemesterPdf, ModuleDescriptionPdf, FormationPlanPdf from cms.models import (Domaine, Processus, Module, Competence, Document, UploadDoc,) @@ -85,8 +84,7 @@ class DocumentDetailView(DetailView): class UploadDetailView(DetailView): """ - Affiche les documents uploadés à la suite des doc. - DocumentsInline + Display first recorded documents and next uploaded documents """ template_name = 'cms/upload_detail.html' model = UploadDoc @@ -100,7 +98,7 @@ class UploadDetailView(DetailView): def print_module_pdf(request, pk): filename = 'module.pdf' path = os.path.join(tempfile.gettempdir(), filename) - pdf = ModulePdf(path) + pdf = ModuleDescriptionPdf(path) module = Module.objects.get(pk=pk) pdf.produce(module) with open(path, mode='rb') as fh: @@ -112,7 +110,7 @@ def print_module_pdf(request, pk): def print_plan_formation(request): filename = 'plan_formation.pdf' path = os.path.join(tempfile.gettempdir(), filename) - pdf = PlanFormationPdf(path) + pdf = FormationPlanPdf(path) domain = Domaine.objects.all().order_by('code') process = Processus.objects.all().order_by('code') pdf.produce(domain, process) @@ -128,15 +126,8 @@ def print_periode_formation(request): path = os.path.join(tempfile.gettempdir(), filename) context = {} context = get_context(context) - pdf = PeriodeFormationPdf(path) + pdf = PeriodSemesterPdf(path) pdf.produce(context) - """ - for semestre_id in range(1, 7): - modules = context['sem{0}'.format(str(semestre_id))] - total = context['tot{0}'.format(str(semestre_id))] - pdf.produce_half_year(semestre_id, modules, total) - """ - #pdf.print_total(context['tot']) with open(path, mode='rb') as fh: response = HttpResponse(fh.read(), content_type='application/pdf') @@ -146,7 +137,7 @@ def print_periode_formation(request): def get_context(context): """ - Calcul du nombre de périodes de formation + Retrive periods """ liste = Module.objects.exclude(periode_presentiel=0) # context['tot'] = liste.aggregate(Sum(F('periode_presentiel')))