[Django] #36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter` subclasses as a valid element type

8 views
Skip to first unread message

Django

unread,
Mar 12, 2026, 11:00:04 AMMar 12
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
------------------------+-----------------------------------------
Reporter: youtux | Type: Bug
Status: new | Component: Documentation
Version: 6.0 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------+-----------------------------------------
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:

1. A field name
2. A subclass of `django.contrib.admin.SimpleListFilter`
3. A 2-tuple containing a field name and a subclass of
`django.contrib.admin.FieldListFilter`

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)`:

```python
if callable(list_filter):
# This is simply a custom list filter class.
spec = list_filter(request, lookup_params, self.model,
self.model_admin)
```

The 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.

This means a direct `ListFilter` subclass (not going through
`SimpleListFilter`) works perfectly fine:

```python
class MyFilter(admin.ListFilter):
title = "My Filter"
parameter_name = "my_param"
template = "admin/my_filter.html"

def __init__(self, request, params, model, model_admin):
super().__init__(request, params, model, model_admin)
params.pop(self.parameter_name, None)

def has_output(self):
return True

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

def queryset(self, request, queryset):
return queryset

def choices(self, changelist):
yield {"selected": True, "display": "All"}


class MyAdmin(admin.ModelAdmin):
list_filter = [MyFilter]
```

This 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.

The docs should generalise point 2 to say "A subclass of
`django.contrib.admin.ListFilter`" instead of "A subclass of
`django.contrib.admin.SimpleListFilter`"
--
Ticket URL: <https://code.djangoproject.com/ticket/36982>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 12, 2026, 11:03:54 AMMar 12
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+--------------------------------------
Reporter: youtux | Owner: (none)
Type: Bug | Status: new
Component: Documentation | Version: 6.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Description changed by youtux:

Old description:
New description:

The [https://docs.djangoproject.com/en/6.0/ref/contrib/admin/filters/
ModelAdmin List Filters documentation] states that `list_filter` accepts
three types of elements:

1. A field name
2. A subclass of `django.contrib.admin.SimpleListFilter`
3. A 2-tuple containing a field name and a subclass of
`django.contrib.admin.FieldListFilter`

However, 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)`:

{{{
#!python
if callable(list_filter):
# This is simply a custom list filter class.
spec = list_filter(request, lookup_params, self.model,
self.model_admin)
}}}

The 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.

This means a direct `ListFilter` subclass (not going through
`SimpleListFilter`) works perfectly fine:

{{{
#!python
class MyFilter(admin.ListFilter):
title = "My Filter"
parameter_name = "my_param"
template = "admin/my_filter.html"

def __init__(self, request, params, model, model_admin):
super().__init__(request, params, model, model_admin)
params.pop(self.parameter_name, None)

def has_output(self):
return True

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

def queryset(self, request, queryset):
return queryset

def choices(self, changelist):
yield {"selected": True, "display": "All"}


class MyAdmin(admin.ModelAdmin):
list_filter = [MyFilter]
}}}

This 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.

The docs should generalise point 2 to say "A subclass of
`django.contrib.admin.ListFilter`" instead of "A subclass of
`django.contrib.admin.SimpleListFilter`".

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:1>

Django

unread,
Mar 15, 2026, 10:35:31 AMMar 15
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------
Reporter: Alessio Bogon | Owner: (none)
Type: Bug | Status: new
Component: Documentation | Version: 6.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------
Changes (by Lakshya Prasad):

* stage: Unreviewed => Accepted

Comment:

Thanks for the report. This looks like a valid documentation improvement.
The current docs for ModelAdmin.list_filter do not explicitly mention that
bare ListFilter subclasses can be used directly. Accepting the ticket so
a documentation clarification patch can be added.
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:2>

Django

unread,
Mar 15, 2026, 10:36:16 AMMar 15
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------------
Reporter: Alessio Bogon | Owner: Lakshya Prasad
Type: Bug | Status: assigned
Component: Documentation | Version: 6.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Lakshya Prasad):

* owner: (none) => Lakshya Prasad
* status: new => assigned

Comment:

I'd like to work on this ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:3>

Django

unread,
Mar 15, 2026, 1:56:07 PMMar 15
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------------
Reporter: Alessio Bogon | Owner: Lakshya Prasad
Type: Bug | Status: assigned
Component: Documentation | Version: 6.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Lakshya Prasad):

* has_patch: 0 => 1

Comment:

Pull request submitted: https://github.com/django/django/pull/20915

Has patch checked and ready for review.
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:4>

Django

unread,
Mar 18, 2026, 3:16:44 PMMar 18
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------------
Reporter: Alessio Bogon | Owner: Lakshya Prasad
Type: Bug | Status: assigned
Component: Documentation | Version: 6.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Comment (by Lakshya Prasad):

I’ve submitted a pull request for this issue:

https://github.com/django/django/pull/20941
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:5>

Django

unread,
Mar 18, 2026, 3:30:29 PMMar 18
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------------
Reporter: Alessio Bogon | Owner: Lakshya Prasad
Type: Bug | Status: closed
Component: Documentation | Version: 6.0
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Jacob Walls):

* has_patch: 1 => 0
* resolution: => invalid
* status: assigned => closed

Comment:

I don't think we should do this, because `ListFilter` isn't documented,
and the only main branch of other documented subclasses
[https://docs.djangoproject.com/en/6.0/ref/checks/#:~:text=admin.E114%253A
doesn't work here]:

> admin.E114: The value of list_filter[n] must not inherit from
FieldListFilter.
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:6>

Django

unread,
Apr 16, 2026, 8:26:17 AM (22 hours ago) Apr 16
to django-...@googlegroups.com
#36982: Docs for `ModelAdmin.list_filter` don't mention bare `ListFilter`
subclasses as a valid element type
-------------------------------+------------------------------------------
Reporter: Alessio Bogon | Owner: Lakshya Prasad
Type: Bug | Status: closed
Component: Documentation | Version: 6.0
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------------
Changes (by Natalia Bidart):

* stage: Accepted => Unreviewed

Comment:

Updating Triage Stage accordingly.
--
Ticket URL: <https://code.djangoproject.com/ticket/36982#comment:7>
Reply all
Reply to author
Forward
0 new messages