#27116: Deferrable Admin Filters
-------------------------------+------------------------------------
Reporter: malefice | Owner: nobody
Type: New feature | Status: new
Component: contrib.admin | Version: master
Severity: Normal | Keywords: admin SimpleListFilter
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+------------------------------------
Hi Guys!
I implemented a custom `SimpleListFilter` for one of my projects, but due
to the nature of what it does, it is a very expensive process. It
involves, from a base queryset, splitting it into two copies and then
performing additional filtering (different for each split), prefetching
different objects per split, performing validation vs those prefetch
objects, and then return `pk` values of all positive matches as a brand
new queryset using `__in` lookup.
I read the django admin code, and due to the lazy evaluation of querysets,
my custom `SimpleListFilter` ends up having to go through all entries of
the model, even though there are other filters in place. Maybe my own code
can use some optimizations, but is there any plausible use case for
deferrable admin filters?
Basically, it should perform all other admin filtering first, so that the
base queryset will be as small as possible which will limit the entries
and also limit the number of `Prefetch()` objects. I was able to hack up
some code (shown below) that does this, but is it sound to implement it
out-of-the-box?
{{{
from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
class MyTestFilter(admin.SimpleListFilter):
# ...
defer = True
# ...
class MyTestChangeList(ChangeList):
# ...
def get_filters(self, request):
filter_specs, status, lookup_params, use_distinct =
super(MyTestChangeList, self).get_filters(request)
revised_filter_specs = []
deferred_filter_specs = []
for filter_spec in filter_specs:
if hasattr(filter_spec, 'defer') and filter_spec.defer:
deferred_filter_specs.append(filter_spec)
else:
revised_filter_specs.append(filter_spec)
self.deferred_filter_specs = deferred_filter_specs
return revised_filter_specs, status, lookup_params, use_distinct
def get_queryset(self, request):
qs = super(MyTestChangeList, self).get_queryset(request)
for filter_spec in self.deferred_filter_specs:
new_qs = filter_spec.queryset(request, qs)
if new_qs is not None:
qs = new_qs
return qs
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27116>
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 post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.a67d5a835eacbd81058869193ea71a93%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.