ModelAdmin List Filters¶ModelAdmin classes can define list filters that appear in the right sidebar
of the change list page of the admin, as illustrated in the following
screenshot:
To activate per-field filtering, set ModelAdmin.list_filter to a list
or tuple of elements, where each element is one of the following types:
django.contrib.admin.SimpleListFilter.django.contrib.admin.FieldListFilter.See the examples below for discussion of each of these options for defining
list_filter.
The simplest option is to specify the required field names from your model.
Each specified field should be either a BooleanField, CharField,
DateField, DateTimeField, IntegerField, ForeignKey or
ManyToManyField, for example:
class PersonAdmin(admin.ModelAdmin):
    list_filter = ["is_staff", "company"]
list_filter 中的字段名也可以使用 __ 查找来跨越关系,例如:
class PersonAdmin(admin.UserAdmin):
    list_filter = ["company__name"]
SimpleListFilter¶For custom filtering, you can define your own list filter by subclassing
django.contrib.admin.SimpleListFilter. You need to provide the title
and parameter_name attributes, and override the lookups and
queryset methods, e.g.:
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¶Finally, if you wish to specify an explicit filter type to use with a field you
may provide a list_filter item as a 2-tuple, where the first element is a
field name and the second element is a class inheriting from
django.contrib.admin.FieldListFilter, for example:
class PersonAdmin(admin.ModelAdmin):
    list_filter = [
        ("is_staff", admin.BooleanFieldListFilter),
    ]
这里"is_staff"字段将使用"BooleanFieldListFilter"。在大多数情况下,只指定字段名的字段会自动使用适当的过滤器,但这种格式允许您控制所使用的过滤器。
下面的示例显示了您需要选择使用的可用过滤器类别。
你可以使用 RelatedOnlyFieldListFilter 将相关模型的选择限制在该关系所涉及的对象上:
class BookAdmin(admin.ModelAdmin):
    list_filter = [
        ("author", admin.RelatedOnlyFieldListFilter),
    ]
Assuming author is a ForeignKey to a User model, this will
limit the list_filter choices to the users who have written a book,
instead of listing all users.
你可以使用 EmptyFieldListFilter 来过滤空值,它既可以过滤空字符串也可以过滤空值,这取决于字段允许存储的内容:
class BookAdmin(admin.ModelAdmin):
    list_filter = [
        ("title", admin.EmptyFieldListFilter),
    ]
By defining a filter using the __in lookup, it is possible to filter for
any of a group of values. You need to override the expected_parameters
method, and the specify the lookup_kwargs attribute with the appropriate
field name. By default, multiple values in the query string will be separated
with commas, but this can be customized via the list_separator attribute.
The following example shows such a filter using the vertical-pipe character as
the 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 字段。
List filters typically appear only if the filter has more than one choice. A
filter's has_output() method controls whether or not it appears.
可以指定一个自定义模板来呈现列表过滤器:
class FilterWithCustomTemplate(admin.SimpleListFilter):
    template = "custom_template.html"
具体的例子请看 Django 提供的默认模板(admin/filter.html)。
By default, counts for each filter, known as facets, can be shown by toggling
on via the admin UI. These counts will update according to the currently
applied filters. See ModelAdmin.show_facets for more details.
12月 05, 2023