2đź‘Ť
Here is what worked for me… The “TypeListFilter” is only visible once the “Category” filter is used and then displays all the entries that are a “subTypeOf” the selected category. The “special case” hack further down ensures that the filter disappears when the user selects another Category.
The “_class” parameter adds some extra flexibility. I am using the same filter with different but related Type classes and just have to override this one parameter. Just replace it by the admin.Model class that you want to filter.
class TypeListFilter( admin.SimpleListFilter):
"""
Provide filter for DnaComponentType (the actual "second level" type).
This filter has one cosmetic problem, which is that it's setting is not
automatically deleted if the category filter is changed. I tried but the
request and queryset are all immutable. Instead, the queryset method is
checking for any missmatch between category and filter name and filtering
is ignored if the category name doesn't match the current subType name.
"""
title = 'Type'
parameter_name = 'type'
_class = None
def lookups(self, request, model_admin):
"""
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
"""
if not u'category' in request.GET:
return ()
category_name = request.GET[u'category']
types = self._class.objects.filter(subTypeOf__name=category_name)
return ( (t.name, t.name) for t in types )
def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""
if not u'category' in request.GET:
return queryset
category = request.GET[u'category']
subtypes = self._class.objects.filter(subTypeOf__name=category)
r = queryset.filter(componentType__subTypeOf__name=category)
if not self.value():
return r
## special case: missmatch between subtype and category
## which happens after switching the category
if len(subtypes.filter(name=self.value())) == 0:
return r
return r.filter(componentType__name=self.value())
1đź‘Ť
Found your question as I was looking for something else.
Here’s what I did to only show players that had characters in a selected game:
def lookups(self, request, model_admin):
game_id = request.GET.get('game', None)
players = Player.objects.all()
if game_id:
players = players.filter(character__game_id=game_id)
return [(p.id, p.__unicode__()) for p in players]
Looks like this is what dan-klasson suggested too.
Hint: Putting ids into query parameters is generally considered a no-no for security reasons.
- [Django]-Mock function arguments in python
- [Django]-Django didn't return an HttpResponse object
- [Django]-How to hide Python & Django technologies from Wappalyzer
- [Django]-Django "migrate" consuming too much CPU