#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:

> 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`"

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 <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019ce293414a-4297e195-84a1-42a4-8f82-8992e7300c6c-000000%40eu-central-1.amazonses.com.

Reply via email to