photo26/photologue/forms.py
2026-04-25 01:02:48 +02:00

160 lines
5.1 KiB
Python

# This file is part of photo21
# Copyright (C) 2022 Amicale des élèves de l'ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import datetime
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Div, Layout, Submit
from django import forms
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from .models import Gallery, Tag
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
allowed_extensions = [
"jpg",
"jpeg",
"png",
"gif",
"tiff",
] # Specify allowed extensions here
def __init__(self, *args, **kwargs):
kwargs.setdefault(
"widget",
MultipleFileInput(
attrs={
"accept": "image/*",
"class": "mb-3",
}
),
)
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [self.validate_file(d, single_file_clean, initial) for d in data]
else:
result = self.validate_file(data, single_file_clean, initial)
return result
def validate_file(self, file, single_file_clean, initial):
# Perform the default clean
cleaned_file = single_file_clean(file, initial)
# Check the file extension
extension = file.name.split(".")[-1].lower()
if extension not in self.allowed_extensions:
raise forms.ValidationError(
f"{file.name} has an invalid file extension. "
f"Allowed extensions are: {', '.join(self.allowed_extensions)}"
)
return cleaned_file
class UploadForm(forms.Form):
file_field = MultipleFileField(label="")
gallery = forms.ModelChoiceField(
Gallery.objects.all(),
label=_("Gallery"),
required=False,
empty_label=_("-- Create a new gallery --"),
help_text=_(
"Select a gallery to add these images to. Leave this empty to "
"create a new gallery from the supplied title."
),
)
new_gallery_title = forms.CharField(
label=_("New gallery title"),
max_length=250,
required=False,
)
new_gallery_date_start = forms.DateField(
label=_("New gallery event start date"),
initial=datetime.date.today,
required=False,
)
new_gallery_date_end = forms.DateField(
label=_("New gallery event end date"),
initial=datetime.date.today,
required=False,
)
new_gallery_description = forms.CharField(
widget=forms.Textarea(attrs={"rows": 4}),
label=_("Description"),
required=False,
)
new_gallery_tags = forms.ModelMultipleChoiceField(
Tag.objects.all(),
label=_("New gallery tags"),
required=False,
help_text=_(
'Hold down "Control", or "Command" on a Mac, to select more than one.'
),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.use_custom_control = False
self.helper.layout = Layout(
"file_field",
"gallery",
"new_gallery_title",
Div(
Div("new_gallery_date_start", css_class="col"),
Div("new_gallery_date_end", css_class="col"),
css_class="row",
),
"new_gallery_description",
"new_gallery_tags",
Submit("submit", _("Upload"), css_class="btn btn-success mt-2"),
)
def clean(self):
cleaned_data = super().clean()
# Check that either an existing gallery is chosen, or new_gallery_title is filled
if not (
bool(cleaned_data["gallery"])
^ bool(cleaned_data.get("new_gallery_title", None))
):
raise forms.ValidationError(
_("Select an existing gallery, or enter a title for a new gallery.")
)
return cleaned_data
def get_or_create_gallery(self):
"""
Get or create gallery
"""
gallery = self.cleaned_data["gallery"]
if not gallery:
# Create new gallery
title = self.cleaned_data.get("new_gallery_title")
base_slug = slugify(title)
slug = base_slug
counter = 2
while Gallery.objects.filter(slug=slug).exists():
slug = f"{base_slug}-{counter}"
counter += 1
gallery = Gallery.objects.create(
title=title,
slug=slug,
date_start=self.cleaned_data["new_gallery_date_start"],
date_end=self.cleaned_data["new_gallery_date_end"],
description=self.cleaned_data["new_gallery_description"],
)
for tag in self.cleaned_data["new_gallery_tags"]:
gallery.tags.add(tag)
return gallery