- Author:
- onlinehero
- Posted:
- January 21, 2010
- Language:
- Python
- Version:
- 1.1
- Score:
- 3 (after 3 ratings)
When doing a list_filter on some object in the Django interface, every single item will be displayed. This is not always smart when very long list of choices can be displayed, even though the majority of these choices might not even exist in the database at all.
Using this script will only display a filtering possibility for those items actually present in the database.
This script is not generic, and you will need to change the lines noted "Change this", since I cannot know what exactly you need to filter.
There is possibly a way to make this completely generic, and I hope this will inspire someone to make it!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # admin.py
# The list of objects can get extremely long. This method will
# override the filter-method for objects by specifying an extra
# attribute on the list of choices, thus only displaying a filter
# method to those objects actually existing in the database.
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__id__exact' % f.name # Change this to match the search of your object
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.objects = model.objects.all()
def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
# Filter the call - change i.item to whatever you are filtering on
items = [i.item for i in self.objects]
for k in items:
yield {'selected': smart_unicode(k) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: k.id}), # Change .id to match what you are searching for
'display': k}
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'compact_filter', False), CustomChoiceFilterSpec))
# models.py
# This is just an example
origin = models.CharField(max_length=2, choices=COUNTRIES, verbose_name='Country of origin')
# Add this to the item
origin.compact_filter = True
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Hi onlinehero,
thank you very much for your fantastic snippets. In my Django installation (1.1) it seems that your code had a bug. I changed the line number 20 in this way (items = set([i.item for i in self.objects])). I also make some changes to add a counter beside the label of the filter and to manage objects without foreignkey value set.
You can find below my code:
#
Please login first before commenting.