# Django 5.0.9.dev20240806133106 ドキュメント

# `ModelAdmin` リストフィルタ

`ModelAdmin` クラスは、以下のスクリーンショットのように、admin アプリケーションの変更一覧ページの右サイドバーに表示されるリストフィルタを定義できます:

フィールドごとのフィルタリングを有効にするには、`ModelAdmin.list_filter` を要素のリストまたはタプルに設定し、各要素が以下のいずれかのタイプでなければなりません:

- フィールド名。
- `django.contrib.admin.SimpleListFilter` のサブクラス。
- フィールド名と `django.contrib.admin.FieldListFilter` のサブクラスを含む 2値タプル。

`list_filter` を定義するための各オプションについては、以下の例を参照してください。

## フィールド名を使用する

最も簡単なオプションは、モデルから必須のフィールド名を指定することです。

指定するフィールドは `BooleanField`, `CharField`, `DateField`, `DateTimeField`, `IntegerField`, `ForeignKey` または `ManyToManyField` のいずれかでなければなりません:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = ["is_staff", "company"]

`list_filter` 内のフィールド名は `__` ルックアップを使って関係先を参照できます。たとえば、次のように参照できます。

    class PersonAdmin(admin.UserAdmin):
        list_filter = ["company__name"]

## `SimpleListFilter` を使用する

フィルタリングをカスタマイズするには、 `django.contrib.admin.SimpleListFilter` をサブクラス化して独自のリストフィルタを定義します。 `title` と `parameter_name` 属性を指定し、 `lookups` と `queryset` メソッドをオーバーライドする必要があります:

    from datetime import date

    from django.contrib import admin
    from django.utils.translation import gettext_lazy as _

    class DecadeBornListFilter(admin.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(admin.ModelAdmin):
        list_filter = [DecadeBornListFilter]

注釈

利便性のため、`HttpRequest` オブジェクトが `lookups` と `queryset` メソッドに渡されます。たとえば、次のようにします。

    class AuthDecadeBornListFilter(DecadeBornListFilter):
        def lookups(self, request, model_admin):
            if request.user.is_superuser:
                return super().lookups(request, model_admin)

        def queryset(self, request, queryset):
            if request.user.is_superuser:
                return super().queryset(request, queryset)

たとえば利用可能なデータに基づくルックアップを行いたい場合などに便利なように、`ModelAdmin` オブジェクトは `lookups` メソッドに渡されます。

    class AdvancedDecadeBornListFilter(DecadeBornListFilter):
        def lookups(self, request, model_admin):
            """
            Only show the lookups if there actually is
            anyone born in the corresponding decades.
            """
            qs = model_admin.get_queryset(request)
            if qs.filter(
                birthday__gte=date(1980, 1, 1),
                birthday__lte=date(1989, 12, 31),
            ).exists():
                yield ("80s", _("in the eighties"))
            if qs.filter(
                birthday__gte=date(1990, 1, 1),
                birthday__lte=date(1999, 12, 31),
            ).exists():
                yield ("90s", _("in the nineties"))

## フィールド名と明示的な `FieldListFilter` を使用する

最後に、フィールドに使用する明示的なフィルタタイプを指定したい場合は、2値タプルとして `list_filter` 項目を指定できます。最初の要素はフィールド名で、2番目の要素は `django.contrib.admin.FieldListFilter` を継承したクラスです。例:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = [
            ("is_staff", admin.BooleanFieldListFilter),
        ]

ここでは `is_staff` フィールドは `BooleanFieldListFilter` を使用します。ほとんどの場合、フィールド名を指定するだけでフィールドは自動的に適切なフィルタを使用しますが、この形式では使用するフィルタを制御できます。

以下の例は、使用するためにオプトインする必要がある利用可能なフィルタクラスを示します。

リレーション先モデルの選択肢を、そのリレーションに含まれるオブジェクトに限定できます。これには `RelatedOnlyFieldListFilter` を使用します:

    class BookAdmin(admin.ModelAdmin):
        list_filter = [
            ("author", admin.RelatedOnlyFieldListFilter),
        ]

`author` が `User` モデルの `ForeignKey` であるとすると、これは `list_filter` の選択肢を、すべてのユーザーではなく、本を書いたユーザーに制限します。

空の値は `EmptyFieldListFilter` を使ってフィルタリングできます。これは、フィールドが何を保存できるかに応じて、空の文字列と NULL の両方をフィルタリングできます:

    class BookAdmin(admin.ModelAdmin):
        list_filter = [
            ("title", admin.EmptyFieldListFilter),
        ]

`__in` ルックアップを使用してフィルタを定義することで、任意の値のいずれかでフィルタリングできます。`expected_parameters` メソッドをオーバーライドし、適切なフィールド名を持つ `lookup_kwargs` 属性を指定する必要があります。クエリ文字列内の複数の値はデフォルトでカンマで区切られますが、これは `list_separator` 属性を介してカスタマイズできます。以下の例は、縦棒文字を区切り文字として使用するフィルタを示しています:

    class FilterWithCustomSeparator(admin.FieldListFilter):
        # custom list separator that should be used to separate values.
        list_separator = "|"

        def __init__(self, field, request, params, model, model_admin, field_path):
            self.lookup_kwarg = "%s__in" % field_path
            super().__init__(field, request, params, model, model_admin, field_path)

        def expected_parameters(self):
            return [self.lookup_kwarg]

注釈

`GenericForeignKey` フィールドはサポートされていません。

リストフィルタは通常、フィルタに複数の選択肢がある場合にのみ表示されます。フィルタの `has_output()` メソッドは、フィルタが表示されるかどうかを制御します。

リストフィルタのレンダリングにはカスタムテンプレートを指定できます:

    class FilterWithCustomTemplate(admin.SimpleListFilter):
        template = "custom_template.html"

具体的な例については、Django により提供されるデフォルトのテンプレート (`admin/filter.html`) を参照してください。

## ファセット (Facet)

New in Django 5.0.

デフォルトでは、ファセット (facet) と呼ばれる各フィルタのカウントは、admin UIからトグルで表示できます。これらのカウントは現在適用されているフィルタに応じて更新されます。詳細は `ModelAdmin.show_facets` を参照してください。