PDF documents

This commit is contained in:
alazo 2017-11-02 14:56:11 +01:00
parent b4191a30f9
commit 511f21eb4d
2 changed files with 86 additions and 80 deletions

View file

@ -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)

View file

@ -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')))