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