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