#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 django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to