Changes between Initial Version and Version 1 of Ticket #36982


Ignore:
Timestamp:
Mar 12, 2026, 10:03:47 AM (3 hours ago)
Author:
Alessio Bogon
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #36982 – Description

    initial v1  
    1 The [ModelAdmin List Filters documentation](https://docs.djangoproject.com/en/6.0/ref/contrib/admin/filters/) states that `list_filter` accepts three types of elements:
     1The [https://docs.djangoproject.com/en/6.0/ref/contrib/admin/filters/ ModelAdmin List Filters documentation] states that `list_filter` accepts three types of elements:
    22
    331. A field name
     
    553. A 2-tuple containing a field name and a subclass of `django.contrib.admin.FieldListFilter`
    66
    7 However, the actual implementation in `ChangeList.get_filters()` ([source](https://github.com/django/django/blob/3180ddb3f532ef246d318d64225886b7c0593676/django/contrib/admin/views/main.py#L188-L190)) accepts **any callable** — including bare `ListFilter` subclasses — and instantiates them with `(request, lookup_params, self.model, self.model_admin)`:
     7However, the actual implementation in `ChangeList.get_filters()` ([https://github.com/django/django/blob/3180ddb3f532ef246d318d64225886b7c0593676/django/contrib/admin/views/main.py#L188-L190 source]) accepts **any callable** — including bare `ListFilter` subclasses — and instantiates them with `(request, lookup_params, self.model, self.model_admin)`:
    88
    9 ```python
     9{{{
     10#!python
    1011if callable(list_filter):
    1112    # This is simply a custom list filter class.
    1213    spec = list_filter(request, lookup_params, self.model, self.model_admin)
    13 ```
     14}}}
    1415
    1516The entire admin filter rendering pipeline (`ChangeList.get_filters()`, `ChangeList.get_queryset()`, and the `admin_list_filter` template tag) only uses methods defined on `ListFilter` itself: `has_output()`, `expected_parameters()`, `queryset()`, `choices()`, `title`, and `template`. Nothing requires `SimpleListFilter` specifically.
     
    1718This means a direct `ListFilter` subclass (not going through `SimpleListFilter`) works perfectly fine:
    1819
    19 ```python
     20{{{
     21#!python
    2022class MyFilter(admin.ListFilter):
    2123    title = "My Filter"
     
    4244class MyAdmin(admin.ModelAdmin):
    4345    list_filter = [MyFilter]
    44 ```
     46}}}
    4547
    4648This is useful when you need full control over the filter (custom template, multi-value parameters, etc.) without the constraints of `SimpleListFilter`'s `lookups()`/`value()` API or `FieldListFilter`'s field introspection.
    4749
    48 The docs should generalise point 2 to say "A subclass of `django.contrib.admin.ListFilter`" instead of "A subclass of `django.contrib.admin.SimpleListFilter`"
     50The docs should generalise point 2 to say "A subclass of `django.contrib.admin.ListFilter`" instead of "A subclass of `django.contrib.admin.SimpleListFilter`".
Back to Top