From 56f49d0af4111f8d54e6dbd93bfe8e28748c52c6 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 16 Jun 2018 19:57:27 +0200 Subject: [PATCH] Factorized zipped export views in a base class --- common/urls.py | 5 ++-- stages/admin.py | 31 ++++----------------- stages/views/__init__.py | 59 ++++++++++++++++++++++------------------ stages/views/base.py | 26 +++++++++++++++++- 4 files changed, 67 insertions(+), 54 deletions(-) diff --git a/common/urls.py b/common/urls.py index 7dd62f4..708d65d 100644 --- a/common/urls.py +++ b/common/urls.py @@ -25,7 +25,7 @@ urlpatterns = [ path('classes/', views.KlassListView.as_view(), name='classes'), path('classes//', views.KlassView.as_view(), name='class'), path('classes//import_reports/', views.ImportReportsView.as_view(), name='import-reports'), - path('classes/print_klass_list/', views.print_klass_list, name='print-klass-list'), + path('classes/print_klass_list/', views.PrintKlassList.as_view(), name='print-klass-list'), path('candidate//send_convocation/', candidats_views.ConvocationView.as_view(), name='candidate-convocation'), @@ -47,7 +47,8 @@ urlpatterns = [ path('imputations/export/', views.export.imputations_export, name='imputations_export'), path('export_sap/', views.export.export_sap, name='export_sap'), - path('print/update_form/', views.print_update_form, name='print_update_form'), + path('print/update_form/', views.PrintUpdateForm.as_view(), name='print_update_form'), + path('print/charge_sheet/', views.PrintChargeSheet.as_view(), name='print-charge-sheet'), path('general_export/', views.export.general_export, name='general-export'), path('ortra_export/', views.export.ortra_export, name='ortra-export'), diff --git a/stages/admin.py b/stages/admin.py index d84d436..cfc2d8f 100644 --- a/stages/admin.py +++ b/stages/admin.py @@ -1,11 +1,7 @@ -import os -import tempfile -import zipfile - from django import forms from django.contrib import admin from django.db import models -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseRedirect from django.urls import reverse from django.utils.html import format_html @@ -14,29 +10,14 @@ from .models import ( CorpContact, Domain, Period, Availability, Training, Course, LogBookReason, LogBook, ExamEDESession, SupervisionBill ) -from .pdf import ChargeSheetPDF def print_charge_sheet(modeladmin, request, queryset): - """ - Génère un pdf pour chaque enseignant, écrit le fichier créé - dans une archive et renvoie une archive de pdf - """ - filename = 'archive_FeuillesDeCharges.zip' - path = os.path.join(tempfile.gettempdir(), filename) - - with zipfile.ZipFile(path, mode='w', compression=zipfile.ZIP_DEFLATED) as filezip: - for teacher in queryset: - activities = teacher.calc_activity() - pdf = ChargeSheetPDF(teacher) - pdf.produce(activities) - filezip.write(pdf.filename) - - with open(filezip.filename, mode='rb') as fh: - response = HttpResponse(fh.read(), content_type='application/zip') - response['Content-Disposition'] = 'attachment; filename="{0}"'.format(filename) - return response - + return HttpResponseRedirect( + reverse('print-charge-sheet') + '?ids=%s' % ",".join( + request.POST.getlist(admin.ACTION_CHECKBOX_NAME) + ) + ) print_charge_sheet.short_description = "Imprimer les feuilles de charge" diff --git a/stages/views/__init__.py b/stages/views/__init__.py index 4f7989f..5eeac47 100644 --- a/stages/views/__init__.py +++ b/stages/views/__init__.py @@ -4,7 +4,6 @@ import re from subprocess import PIPE, Popen, call import tempfile -import zipfile from collections import OrderedDict from datetime import date, datetime, timedelta @@ -27,14 +26,17 @@ from django.utils.translation import ugettext as _ from django.utils.text import slugify from django.views.generic import DetailView, FormView, TemplateView, ListView -from .base import EmailConfirmationBaseView +from .base import EmailConfirmationBaseView, ZippedFilesBaseView from .export import OpenXMLExport from ..forms import EmailBaseForm, PeriodForm, StudentImportForm, UploadHPFileForm, UploadReportForm from ..models import ( Klass, Section, Option, Student, Teacher, Corporation, CorpContact, Course, Period, Training, Availability ) -from ..pdf import ExpertEdeLetterPdf, UpdateDataFormPDF, MentorCompensationPdfForm, KlassListPDF +from ..pdf import ( + ChargeSheetPDF, ExpertEdeLetterPdf, UpdateDataFormPDF, MentorCompensationPdfForm, + KlassListPDF, +) from ..utils import is_int, school_year_start @@ -740,21 +742,18 @@ class StudentConvocationExaminationView(EmailConfirmationView): student.save() -def print_update_form(request): +class PrintUpdateForm(ZippedFilesBaseView): """ PDF form to update personal data """ - tmp_file = tempfile.NamedTemporaryFile() - with zipfile.ZipFile(tmp_file, mode='w', compression=zipfile.ZIP_DEFLATED) as filezip: - for klass in Klass.objects.filter(level__gte=2).exclude(section__name='MP_ASSC').exclude(section__name='MP_ASE'): + filename = 'modification.zip' + + def generate_files(self): + for klass in Klass.objects.filter(level__gte=2 + ).exclude(section__name='MP_ASSC').exclude(section__name='MP_ASE'): pdf = UpdateDataFormPDF('{0}.pdf'.format(klass.name)) pdf.produce(klass) - filezip.write(pdf.filename) - - with open(filezip.filename, mode='rb') as fh: - response = HttpResponse(fh.read(), content_type='application/zip') - response['Content-Disposition'] = 'attachment; filename="modification.zip"' - return response + yield pdf.filename def print_expert_ede_compensation_form(request, pk): @@ -796,19 +795,27 @@ def print_mentor_ede_compensation_form(request, pk): return response -def print_klass_list(request): - query = Klass.active.order_by('section', 'name') +class PrintKlassList(ZippedFilesBaseView): + filename = 'archive_RolesDeClasses.zip' - filename = 'archive_RolesDeClasses.zip' - path = os.path.join(tempfile.gettempdir(), filename) + def generate_files(self): + for klass in Klass.active.order_by('section', 'name'): + pdf = KlassListPDF(klass) + pdf.produce(klass) + yield pdf.filename - with zipfile.ZipFile(path, mode='w', compression=zipfile.ZIP_DEFLATED) as filezip: - for klass in query: - pdf = KlassListPDF(klass) - pdf.produce(klass) - filezip.write(pdf.filename) - with open(filezip.filename, mode='rb') as fh: - response = HttpResponse(fh.read(), content_type='application/zip') - response['Content-Disposition'] = 'attachment; filename="{0}"'.format(filename) - return response +class PrintChargeSheet(ZippedFilesBaseView): + """ + Génère un pdf pour chaque enseignant, écrit le fichier créé + dans une archive et renvoie une archive de pdf + """ + filename = 'archive_FeuillesDeCharges.zip' + + def generate_files(self): + queryset = Teacher.objects.filter(pk__in=self.request.GET.get('ids').split(',')) + for teacher in queryset: + activities = teacher.calc_activity() + pdf = ChargeSheetPDF(teacher) + pdf.produce(activities) + yield pdf.filename diff --git a/stages/views/base.py b/stages/views/base.py index 3145244..6bc7938 100644 --- a/stages/views/base.py +++ b/stages/views/base.py @@ -1,7 +1,12 @@ +import os +import tempfile +import zipfile + from django.contrib import messages from django.core.mail import EmailMessage +from django.http import HttpResponse from django.urls import reverse_lazy -from django.views.generic import FormView +from django.views.generic import FormView, View from stages.forms import EmailBaseForm @@ -44,3 +49,22 @@ class EmailConfirmationBaseView(FormView): 'title': self.title, }) return context + + +class ZippedFilesBaseView(View): + """A base class to return a .zip file containing a compressed list of files.""" + filename = 'to_be_defined.zip' + + def generate_files(self): + raise NotImplementedError() + + def get(self, request, *args, **kwargs): + tmp_file = tempfile.NamedTemporaryFile() + with zipfile.ZipFile(tmp_file, mode='w', compression=zipfile.ZIP_DEFLATED) as filezip: + for file_name in self.generate_files(): + filezip.write(file_name, arcname=os.path.basename(file_name)) + + with open(filezip.filename, mode='rb') as fh: + response = HttpResponse(fh.read(), content_type='application/zip') + response['Content-Disposition'] = 'attachment; filename="%s"' % self.filename + return response