Allow SVG club logos

ImageField validates uploads through Pillow, which can't read SVGs, so
a club crest that's a vector logo was rejected outright. Switches to a
plain FileField with an extension allowlist (png/jpg/jpeg/gif/webp/svg)
instead, and restricts the file picker to image types via the widget's
accept attribute.
This commit is contained in:
2026-07-27 10:27:07 +02:00
parent 075c2918b6
commit 88a6c63f9f
3 changed files with 31 additions and 2 deletions

View File

@@ -0,0 +1,20 @@
# Generated by Django 6.0.6 on 2026-07-24 16:40
import club.models
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('club', '0014_club_secondary_color'),
]
operations = [
migrations.AlterField(
model_name='club',
name='logo',
field=models.FileField(blank=True, help_text="Shown on the club's own pages. Without one, the club's initials are used.", upload_to=club.models.club_logo_path, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'])], verbose_name='logo'),
),
]

View File

@@ -1,6 +1,6 @@
import datetime
from django.core.validators import RegexValidator
from django.core.validators import FileExtensionValidator, RegexValidator
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
@@ -31,7 +31,15 @@ class Club(UUIDModel):
name = models.CharField(_("name"), max_length=255)
slug = models.SlugField(_("slug"), max_length=255, unique=True, blank=True, help_text=_("Drives subdomain / path resolution (e.g. ajax-united.rosterchief.app)."))
logo = models.ImageField(_("logo"), upload_to=club_logo_path, blank=True, help_text=_("Shown on the club's own pages. Without one, the club's initials are used."))
logo = models.FileField(
_("logo"),
upload_to=club_logo_path,
blank=True,
# A plain FileField, not ImageField: Pillow (which ImageField validates through)
# cannot read SVGs, and club crests are commonly vector logos.
validators=[FileExtensionValidator(allowed_extensions=["png", "jpg", "jpeg", "gif", "webp", "svg"])],
help_text=_("Shown on the club's own pages. Without one, the club's initials are used."),
)
primary_color = models.CharField(
_("primary colour"),
max_length=7,

View File

@@ -21,6 +21,7 @@ class ClubForm(forms.ModelForm):
widgets = {
"primary_color": forms.TextInput(attrs={"placeholder": "#1e40af"}),
"secondary_color": forms.TextInput(attrs={"placeholder": "#be185d"}),
"logo": forms.ClearableFileInput(attrs={"accept": "image/png,image/jpeg,image/gif,image/webp,image/svg+xml"}),
}
def __init__(self, *args, **kwargs):