diff --git a/website/photos/admin.py b/website/photos/admin.py index 213511d91..58befe00a 100644 --- a/website/photos/admin.py +++ b/website/photos/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin, messages +from django.db import transaction from django.db.models import Count from django.dispatch import Signal from django.utils.translation import gettext_lazy as _ @@ -56,7 +57,10 @@ def save_model(self, request, obj, form, change): archive = form.cleaned_data.get("album_archive", None) if archive is not None: try: - extract_archive(request, obj, archive) + with transaction.atomic(): + # We make the upload atomic separately, so we can keep using the db if it fails. + # See https://docs.djangoproject.com/en/4.2/topics/db/transactions/#handling-exceptions-within-postgresql-transactions. + extract_archive(request, obj, archive) album_uploaded.send(sender=None, album=obj) except Exception: raise diff --git a/website/photos/services.py b/website/photos/services.py index 2f5253bef..c2809aa59 100644 --- a/website/photos/services.py +++ b/website/photos/services.py @@ -10,6 +10,8 @@ from django.http import Http404 from django.utils.translation import gettext_lazy as _ +from PIL import UnidentifiedImageError + from photos.models import Photo logger = logging.getLogger(__name__) @@ -103,6 +105,7 @@ def _try_save_photo(request, album, file, filename): instance.file = File(file, filename) try: instance.full_clean() + instance.save() except ValidationError as e: errors = e.message_dict if "This photo already exists in this album." in errors.get("file", []): @@ -117,6 +120,9 @@ def _try_save_photo(request, album, file, filename): messages.WARNING, f"{filename} cannot be opened.", ) - return - - instance.save() + except UnidentifiedImageError: + messages.add_message( + request, + messages.WARNING, + f"{filename} cannot be opened.", + )