# Copyright (C) 2021 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later import os import zipfile from io import BytesIO from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.core.mail import mail_managers from django.http import HttpResponse from django.urls import reverse_lazy from django.views.generic.detail import DetailView from django.views.generic.edit import FormView from photologue.models import Gallery from photologue.views import GalleryArchiveIndexView, GalleryYearArchiveView from taggit.models import Tag from .forms import UploadForm class TagDetail(LoginRequiredMixin, DetailView): model = Tag def get_context_data(self, **kwargs): """ Insert the single object into the context dict. """ current_tag = self.get_object().slug context = super().get_context_data(**kwargs) context['galleries'] = Gallery.objects.on_site().is_public() \ .filter(extended__tags__slug=current_tag) \ .order_by('-extended__date_start') return context class CustomGalleryArchiveIndexView(GalleryArchiveIndexView): """ Override to use event date """ date_field = 'extended__date_start' uses_datetime_field = False # Fix related object access class CustomGalleryYearArchiveView(GalleryYearArchiveView): """ Override to use event date """ date_field = 'extended__date_start' uses_datetime_field = False # Fix related object access class CustomGalleryDetailView(DetailView): """ Custom gallery detail view to filter on photo owner """ queryset = Gallery.objects.on_site().is_public() def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Query with extended and owner to reduce database lag context['photos'] = self.object.public().select_related('extended__owner') # List owners context['owners'] = [] for photo in context['photos']: if hasattr(photo, 'extended') and photo.extended.owner not in context['owners']: context['owners'].append(photo.extended.owner) # Filter on owner if 'owner' in self.kwargs: context['photos'] = context['photos'].filter(extended__owner__id=self.kwargs['owner']) return context class GalleryDownload(LoginRequiredMixin, DetailView): model = Gallery def get(self, request, *args, **kwargs): """ Download a zip file of the gallery on GET request. """ # Create zip file with pictures gallery = self.get_object() byte_data = BytesIO() zip_file = zipfile.ZipFile(byte_data, "w") for photo in gallery.public(): filename = os.path.basename(os.path.normpath(photo.image.path)) zip_file.write(photo.image.path, filename) zip_file.close() # Return zip file response = HttpResponse(byte_data.getvalue(), content_type='application/x-zip-compressed') response['Content-Disposition'] = f"attachment; filename={gallery.slug}.zip" return response class GalleryUpload(FormView): """ Form to upload new photos in a gallery """ form_class = UploadForm template_name = "photologue/upload.html" success_url = reverse_lazy("gallery-upload") def form_valid(self, form): # Upload photos # We take files from the request to support multiple upload files = self.request.FILES.getlist('file_field') form.save(self.request.user, files) # Notify user then managers messages.success(self.request, "Photos has been successfully uploaded.") gallery_title = form.cleaned_data['gallery'] or form.cleaned_data.get('new_gallery_title', '') photos = ", ".join(f.name for f in files) mail_managers( subject="New photos upload", message=f"{self.request.user.username} has uploaded in `{gallery_title}`: {photos}", ) return super().form_valid(form)