Comment ajouter des filtres personnalisés à la vue admin de Wagtail Images ?

#Django#Python#Wagtail

par Maxime Decooman

Le défi

L'interface d'administration des images de Wagtail est puissante, mais vous avez parfois besoin de capacités de filtrage supplémentaires. Un besoin courant est le filtrage des images par format de fichier (JPEG, PNG, GIF, WebP, etc.) pour aider les éditeurs à trouver rapidement le bon type d'image.

Cet article vous montre une solution propre et facile à maintenir en utilisant le système de configuration d'application de Django.

La solution élégante

Au lieu de nous débattre avec des surcharges d'URL, nous utiliserons la méthode app ready() de Django pour modifier la classe images.IndexView de Wagtail.

Étape 1 : Créer un jeu de filtres personnalisé

Tout d'abord, créez un jeu de filtres personnalisé qui étend le jeu de filtres existant ImagesFilterSet de Wagtail :

# myproject/core/filters.py
from django_filters import ChoiceFilter
from wagtail.images import get_image_model
from wagtail.images.views.images import ImagesFilterSet

ImageModel = get_image_model()


class CustomImageFilterSet(ImagesFilterSet):
    file_format = ChoiceFilter(
        choices=[
            ('jpeg', 'JPEG'),
            ('jpg', 'JPG'),
            ('png', 'PNG'),
            ('gif', 'GIF'),
            ('webp', 'WebP'),
        ],
        method='filter_by_format',
        label='File Format'
    )

    def filter_by_format(self, queryset, name, value):
        if value:
            return queryset.filter(file__iendswith=f'.{value}')
        return queryset

    class Meta:
        model = ImageModel
        fields = ['file_format']

Étape 2 : Appliquer l'ensemble de filtres à l'aide de la configuration de l'application

Maintenant, utilisez la méthode ready() de votre application Django pour modifier la vue des images :

# myproject/core/apps.py
from django.apps import AppConfig


class CoreConfig(AppConfig):
    """Config for the core app."""

    default = True
    default_auto_field = "django.db.models.BigAutoField"
    name = "myproject.core"

    def ready(self):
        from wagtail.documents.views.documents import IndexView
        from wagtail.images.views.images import IndexView as ImagesIndexView
        from .filters import CustomImageFilterSet

        # Example of other customizations
        IndexView.default_ordering = "-created_at"

        # Apply custom filterset to images admin
        ImagesIndexView.filterset_class = CustomImageFilterSet

That's It!

Avec ces deux fichiers, vous avez maintenant un filtre de format de fichier personnalisé dans votre administration Wagtail images (/admin/images). Le filtre apparaît comme une liste déroulante dans la vue de la liste des images, permettant aux éditeurs de filtrer rapidement les fichiers JPEG, PNG, GIF ou WebP.

Extension de la solution

Vous pouvez facilement ajouter d'autres filtres à votre CustomImageFilterSet :

class CustomImageFilterSet(ImagesFilterSet):
    file_format = ChoiceFilter(
        choices=[
            ('jpeg', 'JPEG'),
            ('jpg', 'JPEG'),
            ('png', 'PNG'),
            ('gif', 'GIF'),
            ('webp', 'WebP'),
        ],
        method='filter_by_format',
        label='File Format'
    )

    # Add more filters
    file_size = ChoiceFilter(
        choices=[
            ('small', 'Small (< 100KB)'),
            ('medium', 'Medium (100KB - 1MB)'),
            ('large', 'Large (> 1MB)'),
        ],
        method='filter_by_size',
        label='File Size'
    )

    def filter_by_format(self, queryset, name, value):
        if value:
            return queryset.filter(file__iendswith=f'.{value}')
        return queryset

    def filter_by_size(self, queryset, name, value):
        if value == 'small':
            return queryset.filter(file_size__lt=100000)
        elif value == 'medium':
            return queryset.filter(file_size__gte=100000, file_size__lt=1000000)
        elif value == 'large':
            return queryset.filter(file_size__gte=1000000)
        return queryset

    class Meta:
        model = ImageModel
        fields = ['file_format', 'file_size']

Approches Alternatives (non recommendées)

J'ai exploré plusieurs autres approches :

  1. URL Override with Hooks - Conduit à des conflits d'espace de noms
  2. Modifié les URLS - Nécessite une gestion complexe et fragile des URLs
  3. Modification de la vue d'Index au complet -Solution trop fragile aux futures mises à jours et peut avoir des effets indésirables.

✅ Une solution maintenable

En exploitant le système de configuration d'application de Django et un "monkey patching", nous avons obtenu une solution propre qui :

  • ajoute un filtrage personnalisé à l'interface d'administration des images de Wagtail
  • Intègre cycle de vie des applications Django
  • maintient une compatibilité totale avec les fonctionnalités existantes
  • évite les conflits d'URL et les problèmes d'espace de noms
  • utilise un minimum de code

Ce modèle peut être appliqué pour personnaliser d'autres interfaces d'administration de Wagtail, ce qui en fait une technique précieuse pour la boîte à outils de tout développeur Wagtail.