i have a model :
class Foo(models.Model):
attribute = models.IntegerField()
user = models.ForeignKey(user)
and a model admin :
class FooAdmin(admin.ModelAdmin):
list_filter = ('attribute',)
In the admin, i’m only displaying Foo objects of the active user but the attribute filter give me all possible attributes even the ones which don’t return any objects for that user. At the end, i have a lot of different filter values, and most of them are useless for the user. How can i limit those filter values to the ones which match the user.
hope it’s understandable
Cheers
Solution :
In the admin.py of your app put :
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
from django.contrib.auth.models import User
from sets import Set
class CustomChoiceFilterSpec(ChoicesFilterSpec):
def __init__(self, f, request, params, model, model_admin):
super(CustomChoiceFilterSpec, self).__init__(f, request, params, model,
model_admin)
self.lookup_kwarg = '%s__attribute__exact' % f.name
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.objects = list(Set([i.attribute for i in model.objects.filter(foo__user = request.user)])) # This is the magic line :) !
def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': ('All')}
for val in self.objects:
yield {'selected': smart_unicode(val) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: val.attribute}),
'display': val.attribute}
def title(self):
return "Attribute"
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'compact_filter', False), CustomChoiceFilterSpec))
the last line says that this type of filter will apply only to objects which have ‘compact_filter’ as an attribute.
So we put in our model Foo (models.py) :
attribute.compact_filter = True
Unfortunately, overriding those list_filters is not easy.
There’s massive progress on writing our own list filters as you can see on this ticket: http://code.djangoproject.com/ticket/5833 but won’t make it for 1.3.
All I can suggest is to start using this new vocabulary: “FilterSpec” to find code snippets from various people who have been able to get their custom FilterSpecs working on SO and on the googles.
Custom Filter in Django Admin on Django 1.3 or below
http://djangosnippets.org/snippets/1051/
I will take this as an opportunity to mess around with FilterSpecs myself!