Say we have two objects:
class Author(models.Model):
name = models.CharField(length=50)
class Book(models.Model):
author = models.ForeignKey(Author)
is_bestseller = models.BooleanField()
In BookAdmin, if we specify
list_filter = ('author', 'is_bestseller')
the choices given to you for 'author' will always be all the authors in the database, no matter whether they've written a bestseller or not.
I'd like choices of my filters to be limited by the current selection. I attempted to do this in a general manner, using admin.SimpleListFilter, however, I'm stuck, since:
model_admin.get_queryset()
returns unfiltered queryset (i.e all objects, not just those currently filtered out by the user).
How do I get the filtered queryset of the BookAdmin?
EDIT: To illustrate the problem better, here is my code:
class ForeignFieldFilter(admin.SimpleListFilter):
field = None
def lookups(self, request, model_admin):
queryset = model_admin.get_queryset(request).select_related(self.field)
# ^^^ !!! Returns UNFILTERED queryset - it's not affected by other filters
field_ids = queryset.values_list(self.field, flat=True)
for field_value in self.model..objects.filter(id__in=field_ids):
yield (field_value.pk, str(field_value))
def queryset(self, request, queryset):
value = self.value()
# Check that any value was passed, if not, return unmodified queryset
if not value:
return queryset
return queryset.filter({'{0}__pk'.format(self.field): value})
def foreign_field_filter_factory(field, model, title=None):
title = title or (field[:1].upper() + field[1:])
return type(
"ForeignFieldFilter_{0}".format(field),
(ForeignFieldFilter,),
{
'field': field,
'title': title,
'parameter_name': field,
'model': model
})
For BookAdmin
class AuthorBestSeller(admin.SimpleListFilter):
title = 'Best selling authors'
parameter_name = 'bestseller'
def queryset(self, request, queryset):
if self.value():
return queryset.filter(author_id=self.value())
else:
return queryset
def lookups(self, request, model_admin):
qs = model_admin.get_queryset(request)
query_attrs = dict([(param, val) for param, val in request.GET.items()])
qs = qs.filter(**query_attrs)
for book in qs.filter(is_bestseller=1): # or might be able to use yeild here
ret.append((book.author_id, book.author))
return ret
edit: humm... this won't quite work either. it will just give you a list of authors with best sellers.
then add to BookAdmin
list_filter = (AuthorBestSeller, )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With