web-dev-qa-db-fra.com

Création de filtres personnalisés pour list_filter dans Django Admin

Je voudrais créer des filtres personnalisés pour l'administrateur Django au lieu des 'is_staff' et 'is_superuser' habituels. J'ai lu ceci list_filter dans les documents Django. Les filtres personnalisés fonctionnent de la manière suivante:

from datetime import date

from Django.utils.translation import ugettext_lazy as _
from Django.contrib.admin import SimpleListFilter

class DecadeBornListFilter(SimpleListFilter):
    # Human-readable title which will be displayed in the
    # right admin sidebar just above the filter options.
    title = _('decade born')

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'decade'

    def lookups(self, request, model_admin):
        """
        Returns a list of tuples. The first element in each
        Tuple is the coded value for the option that will
        appear in the URL query. The second element is the
        human-readable name for the option that will appear
        in the right sidebar.
        """
        return (
            ('80s', _('in the eighties')),
            ('90s', _('in the nineties')),
        )

    def queryset(self, request, queryset):
        """
        Returns the filtered queryset based on the value
        provided in the query string and retrievable via
        `self.value()`.
        """
        # Compare the requested value (either '80s' or '90s')
        # to decide how to filter the queryset.
        if self.value() == '80s':
            return queryset.filter(birthday__gte=date(1980, 1, 1),
                                    birthday__lte=date(1989, 12, 31))
        if self.value() == '90s':
            return queryset.filter(birthday__gte=date(1990, 1, 1),
                                    birthday__lte=date(1999, 12, 31))

class PersonAdmin(ModelAdmin):
    list_filter = (DecadeBornListFilter,)

Mais j'ai déjà créé des fonctions personnalisées pour list_display comme ceci:

def Student_Country(self, obj):
    return '%s' % obj.country
Student_Country.short_description = 'Student-Country'

Est-il possible que je puisse utiliser les fonctions personnalisées pour list_display dans list_filter au lieu d'écrire une nouvelle fonction personnalisée pour list_filter? Toutes les suggestions ou améliorations sont les bienvenues. Besoin de conseils à ce sujet ... Merci ...

44
lakesh

Vous pouvez en effet ajouter des filtres personnalisés aux filtres d'administration en étendant SimpleListFilter. Par exemple, si vous souhaitez ajouter un filtre de continent pour «Afrique» au filtre d'administration de pays utilisé ci-dessus, vous pouvez procéder comme suit:

Dans admin.py:

from Django.contrib.admin import SimpleListFilter

class CountryFilter(SimpleListFilter):
    title = 'country' # or use _('country') for translated title
    parameter_name = 'country'

    def lookups(self, request, model_admin):
        countries = set([c.country for c in model_admin.model.objects.all()])
        return [(c.id, c.name) for c in countries] + [
          ('AFRICA', 'AFRICA - ALL')]

    def queryset(self, request, queryset):
        if self.value() == 'AFRICA':
            return queryset.filter(country__continent='Africa')
        if self.value():
            return queryset.filter(country__id__exact=self.value())

class CityAdmin(ModelAdmin):
    list_filter = (CountryFilter,)
18
Rick Westera

Votre méthode list_display renvoie une chaîne, mais si je comprends bien, ce que vous voulez faire est d’ajouter un filtre qui permet de sélectionner les pays d’étudiants, correct?

Pour ce filtre de relation simple, et en fait pour la colonne d'affichage de liste "Pays-Étudiant", vous n'avez pas besoin de créer de classe de filtre personnalisée ni de méthode d'affichage de liste personnalisée. cela suffirait:

class MyAdmin(admin.ModelAdmin):
    list_display = ('country', )
    list_filter = ('country', )

La manière dont Django procède list_filter, comme expliqué dans la documentation , consiste d’abord à faire correspondre automatiquement les champs que vous fournissez aux classes de filtres prédéfinies; ces filtres incluent CharField et ForeignKey.

list_display automatise de la même manière la population de la colonne de la liste de modifications en utilisant le champ passé en récupérant les objets liés et en renvoyant la valeur unicode de ceux-ci (comme dans la méthode indiquée ci-dessus).

4
tutuDajuju

En plus de Rick Westera answer, voici le Django Docs pour cette situation

ModelAdmin.list_filter
Configurez list_filter pour activer les filtres dans la barre latérale droite de la page de liste de modifications de l'administrateur.
list_filter devrait être une liste ou un tuple d'éléments

0
hasher