#5833: Custom FilterSpecs
-------------------------------------+-------------------------------------
Reporter: | Owner: jkocherhans
Honza_Kral | Status: assigned
Type: New | Component: contrib.admin
feature | Severity: Normal
Milestone: | Keywords: nfa-someday
Version: SVN | list_filter filterspec nfa-
Resolution: | changelist ep2008
Triage Stage: Accepted | Has patch: 1
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 |
-------------------------------------+-------------------------------------
Comment (by julien):
Replying to [comment:118 kmtracey]:
> I experimented with this a bit today, and was able to use the doc to
implement my particular need without too much difficulty so that is good.
Thanks for experimenting with the patch, Karen!
> One thing I thought was odd though was that my filter's `get_query_set`
is called even if its `query_parameter_name` is not in request.GET, and as
a result my `get_query_set` must be coded to handle that case properly
(return the queryset unchanged). If it is not coded properly the result is
that my filter limits the queryset used even when its "All" choice is the
selected choice for it. I think it would be preferable to avoid calling
the `get_query_set` for filters whose query parameters aren't in
`request.GET`.
Yes, that's good point. I'll try to normalise that.
> There is no mention anywhere I could see of why `request` is passed into
`get_choices` and `get_queryset`, nor is it used that I can see anywhere
in the samples. For what kinds of filters might this be used?
It is just there for your convenience in case you want to vary the list of
choices or the list of results, for example, based on who is logged in.
There's a note in the doc for `get_choices()` but not for
`get_query_set()` yet. I'll try to improve the doc.
> My particular use case is a slight modification of an existing admin
filter: I want to filter by a related field, but I only want a subset of
the existing values to appear in the choices. It was not hard to implement
as a !ListFilter but after getting `get_query_set` wrong the first time it
occurred to me it would be better if I could just override the
`get_choices` method for the existing admin filter that already filtered
the way I wanted. Unfortunately that existing admin filter isn't
implemented as a !ListFilter so I can't do that, apparently I'd have to
choose the scary-sounding alternate option of providing a tuple of field
name and class inheriting from !FieldListFilter (which is noted as being
internal and prone to refactoring). Is it not possible to unify things so
that it is easy to both write completely new-and-different filters and
ones that are minor tweaks to what admin already provides?
In your use case it might make more sense to override the
`django.contrib.admin.filterspecs.RelatedFieldListFilter._choices()`
method. However you'll see that its code is quite opaque and not so fun to
play with.
Your remarks make me realise that we should perhaps do a bigger refactor
of the filtering system. The "old" filters (which currently inherit from
`FieldListFilter` in my patch) only take care of managing the query string
and the options to be displayed on the admin UI, where
`ChangeList.get_query_set()` actually does the filtering on the queryset.
This makes sense since both the ChangeList and the filters know how fields
work and how they're supposed to be filtered (e.g. by appending
"`__isnull`" to the field name). However, `ChangeList.get_query_set()`
cannot anticipate how the queryset will be filtered by a custom filter,
and therefore it has to delegate the actual filtering to the custom
`ListFilter` object.
Also, currently the `ListFilter` only allows for one query string
parameter, mostly for the sake of simplicity. However, some field filters
allow for multiple ones, e.g. "`fieldname__exact`" or
"`fieldname__isnull`" for `RelatedFieldListFilter`.
So, to make things more consistent, we should perhaps delegate all that
logic to the filters themselves, including the queryset filtering which is
currently done by the `ChangeList` object for field names.
I'm also going to try and make the field filters follow the new structure,
for example by overriding `get_choices()` to return a list of option
tuples, instead of having to directly yield the iteration items in
`_choices()`. Hopefully this will be possible without too many ugly
internal hacks.
--
Ticket URL: <http://code.djangoproject.com/ticket/5833#comment:119>
Django <http://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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.