[Django] #27116: Deferrable Admin Filters

11 views
Skip to first unread message

Django

unread,
Aug 24, 2016, 6:28:33 AM8/24/16
to django-...@googlegroups.com
#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.

Django

unread,
Aug 24, 2016, 11:10:00 AM8/24/16
to django-...@googlegroups.com
#27116: Deferrable Admin Filters
-------------------------------------+-------------------------------------
Reporter: malefice | Owner: nobody
Type: New feature | Status: closed
Component: contrib.admin | Version: master
Severity: Normal | Resolution: wontfix
Keywords: admin | Triage Stage:
SimpleListFilter | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* status: new => closed
* needs_docs: => 0
* resolution: => wontfix
* needs_tests: => 0
* needs_better_patch: => 0


Comment:

At first glance, it seems to add a non-trivial amount of complexity for
what likely isn't a common use case. Feel free to raise the idea on the
DevelopersMailingList to get more feedback and see if anyone else has a
similar need.

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

Reply all
Reply to author
Forward
0 new messages