From 696bc4d5c11031efeecad3617e208fe647fc0e75 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Sun, 30 Jan 2022 12:29:27 +0100 Subject: [PATCH] Staff members can inspect private pictures --- photologue/models.py | 42 +++-------------- .../admin/photologue/photo/change_list.html | 3 -- .../templates/photologue/gallery_detail.html | 1 + .../photologue/includes/gallery_sample.html | 3 +- .../templates/photologue/photo_detail.html | 2 +- photologue/urls.py | 6 +-- photologue/views.py | 45 +++++++++++++++---- 7 files changed, 49 insertions(+), 53 deletions(-) delete mode 100644 photologue/templates/admin/photologue/photo/change_list.html diff --git a/photologue/models.py b/photologue/models.py index b7e975c..889be06 100644 --- a/photologue/models.py +++ b/photologue/models.py @@ -52,13 +52,6 @@ else: fn = unicodedata.normalize('NFKD', force_str(filename)).encode('ascii', 'ignore').decode('ascii') return os.path.join('photos', fn) -# Support CACHEDIR.TAG spec for backups for ignoring cache dir. -# See http://www.brynosaurus.com/cachedir/spec.html -PHOTOLOGUE_CACHEDIRTAG = os.path.join("photos", "cache", "CACHEDIR.TAG") -if not default_storage.exists(PHOTOLOGUE_CACHEDIRTAG): - default_storage.save(PHOTOLOGUE_CACHEDIRTAG, ContentFile( - b"Signature: 8a477f597d28d172789f06886806bc55")) - # Exif Orientation values # Value 0thRow 0thColumn # 1 top left @@ -181,22 +174,13 @@ class Gallery(models.Model): def get_absolute_url(self): return reverse('photologue:pl-gallery', args=[self.slug]) - def latest(self, limit=LATEST_LIMIT, public=True): - if not limit: - limit = self.photo_count() - if public: - return self.public()[:limit] - else: - return self.photos[:limit] - - def sample(self, count=None, public=True): + def sample(self, public=True): """Return a sample of photos, ordered at random.""" - if not count: - count = 1 + count = 1 if count > self.photo_count(): count = self.photo_count() if public: - photo_set = self.public() + photo_set = self.photos.filter(is_public=True) else: photo_set = self.photos return random.sample(set(photo_set), count) @@ -204,16 +188,12 @@ class Gallery(models.Model): def photo_count(self, public=True): """Return a count of all the photos in this gallery.""" if public: - return self.public().count() + return self.photos.filter(is_public=True).count() else: return self.photos.count() photo_count.short_description = _('count') - def public(self): - """Return a queryset of all the public photos in this gallery.""" - return self.photos.filter(is_public=True) - class ImageModel(models.Model): image = models.ImageField(_('image'), @@ -375,11 +355,6 @@ class ImageModel(models.Model): return # Save the original format im_format = im.format - # Apply effect if found - if self.effect is not None: - im = self.effect.pre_process(im) - elif photosize.effect is not None: - im = photosize.effect.pre_process(im) # Rotate if found & necessary if 'Image Orientation' in self.exif() and \ self.exif().get('Image Orientation').values[0] in IMAGE_EXIF_ORIENTATION_MAP: @@ -388,11 +363,6 @@ class ImageModel(models.Model): # Resize/crop image if (im.size != photosize.size and photosize.size != (0, 0)) or recreate: im = self.resize_image(im, photosize) - # Apply effect if found - if self.effect is not None: - im = self.effect.post_process(im) - elif photosize.effect is not None: - im = photosize.effect.post_process(im) # Save file im_filename = getattr(self, "get_%s_filename" % photosize.name)() try: @@ -515,10 +485,10 @@ class Photo(ImageModel): return self.title def save(self, *args, **kwargs): - # If crop_from or effect property has been changed on existing image, + # If crop_from property has been changed on existing image, # update kwargs to force image recreation in parent class current = Photo.objects.get(pk=self.pk) if self.pk else None - if current and (current.crop_from != self.crop_from or current.effect != self.effect): + if current and (current.crop_from != self.crop_from): kwargs.update(recreate=True) if self.slug is None: diff --git a/photologue/templates/admin/photologue/photo/change_list.html b/photologue/templates/admin/photologue/photo/change_list.html deleted file mode 100644 index 22a98d1..0000000 --- a/photologue/templates/admin/photologue/photo/change_list.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends "admin/change_list.html" %} -{% load i18n %} -{# Hide upload as zip #} \ No newline at end of file diff --git a/photologue/templates/photologue/gallery_detail.html b/photologue/templates/photologue/gallery_detail.html index 1df68af..1263266 100644 --- a/photologue/templates/photologue/gallery_detail.html +++ b/photologue/templates/photologue/gallery_detail.html @@ -39,6 +39,7 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %} {% if gallery.date_start %}

{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} {% trans "to" %} {{ gallery.date_end }}{% endif %}

{% endif %} +{% if not gallery.is_public %}

PRIVATE

{% endif %} {% if gallery.tags.all %}

Tags : {% for tag in gallery.tags.all %} diff --git a/photologue/templates/photologue/includes/gallery_sample.html b/photologue/templates/photologue/includes/gallery_sample.html index 8282074..694fda4 100644 --- a/photologue/templates/photologue/includes/gallery_sample.html +++ b/photologue/templates/photologue/includes/gallery_sample.html @@ -1,12 +1,13 @@ {% load i18n %} -

+
{% for photo in gallery.sample %} {{ photo.title }} {% endfor %}
{{ gallery.title }}
{% if gallery.date_start %}

{{ gallery.date_start }}{% if gallery.date_end and gallery.date_end != gallery.date_start %} - {{ gallery.date_end }}{% endif %}

{% endif %} + {% if not gallery.is_public %}

(private)

{% endif %}
diff --git a/photologue/templates/photologue/photo_detail.html b/photologue/templates/photologue/photo_detail.html index c0d4c1b..24ec51b 100644 --- a/photologue/templates/photologue/photo_detail.html +++ b/photologue/templates/photologue/photo_detail.html @@ -2,7 +2,7 @@ {% comment %} SPDX-License-Identifier: GPL-3.0-or-later {% endcomment %} -{% load photologue_tags i18n %} +{% load i18n %} {% block title %}{{ object.title }}{% endblock %} diff --git a/photologue/urls.py b/photologue/urls.py index e4949f8..ff49533 100644 --- a/photologue/urls.py +++ b/photologue/urls.py @@ -1,6 +1,6 @@ from django.urls import path, re_path -from .views import (CustomGalleryDetailView, GalleryArchiveIndexView, +from .views import (GalleryDetailView, GalleryArchiveIndexView, GalleryDownload, GalleryUpload, GalleryYearArchiveView, PhotoDetailView, TagDetail) @@ -9,8 +9,8 @@ urlpatterns = [ path('tag//', TagDetail.as_view(), name='tag-detail'), path('gallery/', GalleryArchiveIndexView.as_view(), name='pl-gallery-archive'), re_path(r'^gallery/(?P\d{4})/$', GalleryYearArchiveView.as_view(), name='pl-gallery-archive-year'), - path('gallery//', CustomGalleryDetailView.as_view(), name='pl-gallery'), - path('gallery///', CustomGalleryDetailView.as_view(), name='pl-gallery-owner'), + path('gallery//', GalleryDetailView.as_view(), name='pl-gallery'), + path('gallery///', GalleryDetailView.as_view(), name='pl-gallery-owner'), path('gallery//download/', GalleryDownload.as_view(), name='pl-gallery-download'), path('photo//', PhotoDetailView.as_view(), name='pl-photo'), path('upload/', GalleryUpload.as_view(), name='pl-gallery-upload'), diff --git a/photologue/views.py b/photologue/views.py index 77953a8..cf10e0b 100644 --- a/photologue/views.py +++ b/photologue/views.py @@ -24,11 +24,19 @@ from .models import Gallery, Photo, Tag class GalleryDateView(LoginRequiredMixin): - queryset = Gallery.objects.filter(is_public=True) + model = Gallery date_field = 'date_start' uses_datetime_field = False # Fix related object access allow_empty = True + def get_queryset(self): + """Non-staff members only see public galleries""" + qs = super().get_queryset() + if self.request.user.is_staff: + return qs + else: + return qs.filter(is_public=True) + class GalleryArchiveIndexView(GalleryDateView, ArchiveIndexView): pass @@ -39,7 +47,15 @@ class GalleryYearArchiveView(GalleryDateView, YearArchiveView): class PhotoDetailView(LoginRequiredMixin, DetailView): - queryset = Photo.objects.filter(is_public=True) + model = Photo + + def get_queryset(self): + """Non-staff members only see public photos""" + qs = super().get_queryset() + if self.request.user.is_staff: + return qs + else: + return qs.filter(is_public=True) class TagDetail(LoginRequiredMixin, DetailView): @@ -57,17 +73,28 @@ class TagDetail(LoginRequiredMixin, DetailView): return context -class CustomGalleryDetailView(LoginRequiredMixin, DetailView): +class GalleryDetailView(LoginRequiredMixin, DetailView): """ - Custom gallery detail view to filter on photo owner + Gallery detail view to filter on photo owner """ - queryset = Gallery.objects.filter(is_public=True) + model = Gallery + + def get_queryset(self): + """Non-staff members only see public galleries""" + qs = super().get_queryset() + if self.request.user.is_staff: + return qs + else: + return qs.filter(is_public=True) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # Query with owner to reduce database lag - context['photos'] = self.object.public().select_related('owner') + # Non-staff members only see public photos + if self.request.user.is_staff: + context['photos'] = self.object.photos.all() + else: + context['photos'] = self.object.photos.filter(is_public=True) # List owners context['owners'] = [] @@ -83,7 +110,7 @@ class CustomGalleryDetailView(LoginRequiredMixin, DetailView): class GalleryDownload(LoginRequiredMixin, DetailView): - model = Gallery + queryset = Gallery.objects.filter(is_public=True) def get(self, request, *args, **kwargs): """ @@ -93,7 +120,7 @@ class GalleryDownload(LoginRequiredMixin, DetailView): gallery = self.get_object() byte_data = BytesIO() zip_file = zipfile.ZipFile(byte_data, "w") - for photo in gallery.public(): + for photo in gallery.photos.filter(is_public=True): filename = os.path.basename(os.path.normpath(photo.image.path)) zip_file.write(photo.image.path, filename) zip_file.close()