- Author:
- anentropic
- Posted:
- January 12, 2012
- Language:
- Python
- Version:
- 1.3
- Score:
- 3 (after 3 ratings)
Works in Django 1.3
Hopefully it's generic enough to implement a compact (sparse) version of whatever custom filter you need.
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | # utils/admin.py
from operator import itemgetter
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
from django.db.models import Count
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _
def add_compact_filter(field_name,
field_lookup='%s__exact',
field_detector=lambda f: getattr(f, 'compact_filter', False),
field_value_getter=lambda value: value,
filtered_value_getter=None,
filtered_display_getter=None,):
# the simplest case, but they rely on field_name so can't provide as default args
if filtered_value_getter is None:
filtered_value_getter = lambda obj: getattr(obj, field_name)
if filtered_display_getter is None:
filtered_display_getter = lambda obj, count: '%s (%s)' % (getattr(obj, field_name), count)
class CustomChoiceFilterSpec(ChoicesFilterSpec):
def __init__(self, f, request, params, model, model_admin, field_path=None):
super(CustomChoiceFilterSpec, self).__init__(f, request, params, model, model_admin, field_path)
self.lookup_kwarg = field_lookup % f.name
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')}
# get the compact list of filter values
filtered_values = []
counts = {}
for obj in self.objects:
value = filtered_value_getter(obj)
if value in counts:
counts[value] += 1
else:
counts[value] = 1
filtered_values.append((obj, filtered_value_getter(obj)))
filtered = [(value, filtered_display_getter(obj, counts[value])) for obj, value in filtered_values]
for value, display in filtered:
yield {'selected': smart_unicode(value) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: field_value_getter(value)}),
'display': display}
FilterSpec.filter_specs.insert(0, (field_detector, CustomChoiceFilterSpec))
# EXAMPLE usage:
# myapp/admin.py
from utils.admin import add_compact_filter
from .fields import CountryField
add_compact_filter(
field_name='country',
field_lookup='%s__exact',
field_detector=lambda f: isinstance(f, CountryField),
filtered_display_getter=lambda obj, count: '%s (%s)' % (obj.get_country_display(), count),
)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 9 months ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months, 1 week ago
- Serializer factory with Django Rest Framework by julio 1 year, 4 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
- Help text hyperlinks by sa2812 1 year, 5 months ago
Comments
Please login first before commenting.