ModelAdmin 列表过滤器

ModelAdmin 类可以定义出现在管理员更改列表页面右侧边栏中的列表筛选器,如以下屏幕截图所示:

../../../_images/list_filter.png

要激活逐字段筛选,请设置 ModelAdmin.list_filter 元素的列表或元组,其中每个元素是以下类型之一:

  • 一个字段名。

  • 的一个子类 django.contrib.admin.SimpleListFilter

  • 包含字段名和子类的二元组 django.contrib.admin.FieldListFilter

有关定义这些选项的每个选项的讨论,请参阅以下示例 list_filter

使用字段名

最简单的选项是从模型中指定所需的字段名称。

每个指定的字段应为 BooleanFieldCharFieldDateFieldDateTimeFieldIntegerFieldForeignKeyManyToManyField ,例如::

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

中的字段名称 list_filter 还可以使用 __ 查找,例如::

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

使用 SimpleListFilter

对于自定义筛选,您可以通过子类化定义您自己的列表筛选器 django.contrib.admin.SimpleListFilter 。您需要提供 titleparameter_name 属性,并重写 lookupsqueryset 方法,例如:

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 对象被传递给 lookupsqueryset 方法,例如::

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

最后,如果希望指定与字段一起使用的显式筛选器类型,可以提供 list_filter 项作为二元组,其中第一个元素是字段名,第二个元素是从 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 是一种 ForeignKey 到一个 User 模型,这将限制 list_filter 选择给已经写了一本书的用户,而不是列出所有用户。

可以使用以下命令筛选空值 EmptyFieldListFilter ,它可以过滤空字符串和空值,具体取决于字段允许存储的内容::

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 )以获取具体的例子。

小平面

New in Django 5.0.

默认情况下,每个筛选器的计数(称为方面)可以通过管理用户界面打开来显示。这些计数将根据当前应用的过滤器进行更新。看见 ModelAdmin.show_facets 了解更多详细信息。