This closure lets you quickly produce date-style range filters in the Django Admin interface without having to create a new class for each one.
It follows Python range semantics, with the lower value using a _gte test and the upper value using an _lt test.
Here's an example of how I'm using it in one of my projects:
list_filter = ('complete',
        ('chapters', makeRangeFieldListFilter([
            (_('1'), 1, 2),
            (_('2 to 10'), 2, 10),
            (_('11 to 30'), 11, 30),
            (_('31 to 100'), 31, 100),
            (_('At least 100'), 100, None),
        ], nullable=True)),
        ('word_count', makeRangeFieldListFilter([
            (_('Less than 1000'), None, 1000),
            (_('1K to 5K'), 1000, 5000),
            (_('5K to 10K'), 5000, 10000),
            (_('10K to 75K'), 10000, 75000),
            (_('75K to 150K'), 75000, 150000),
            (_('150K to 300K'), 150000, 300000),
            (_('At least 300K'), 300000, None),
        ], nullable=True)),
        ('derivatives_count', makeRangeFieldListFilter([
            (_('None'), 0, 1),
            (_('1 to 5'), 1, 5),
            (_('5 to 50'), 5, 50),
            (_('50 to 1000'), 50, 1000),
            (_('At least 1000'), 1000, None),
        ])),
        'pub_date', 'upd_date')
It is based on code from DateFieldListFilter and BooleanFieldListFilter from django.contrib.admin.filters.
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  | from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import FieldListFilter
def makeRangeFieldListFilter(lookups, nullable=False):
    class RangeFieldListFilter(FieldListFilter):
        def __init__(self, field, request, params, model, model_admin, field_path):
            self.field_generic = '%s__' % field_path
            self.range_params = dict([(k, v) for k, v in params.items()
                                     if k.startswith(self.field_generic)])
            self.lookup_kwarg_start = '%s__gte' % field_path
            self.lookup_kwarg_stop = '%s__lt' % field_path
            self.lookup_kwarg_null = '%s__isnull' % field_path
            self.links = [ (_('Any value'), {}), ]
            for name, start, stop in lookups:
                query_params = {}
                if start is not None:
                    query_params[self.lookup_kwarg_start] = str(start)
                if stop is not None:
                    query_params[self.lookup_kwarg_stop] = str(stop)
                self.links.append((name, query_params))
            if nullable:
                self.links.append((_('Unknown'), {
                    self.lookup_kwarg_null: 'True'
                }))
            super(RangeFieldListFilter, self).__init__(
                field, request, params, model, model_admin, field_path)
        def expected_parameters(self):
            return [
                self.lookup_kwarg_start,
                self.lookup_kwarg_stop,
                self.lookup_kwarg_null
            ]
        def choices(self, cl):
            for title, param_dict in self.links:
                yield {
                    'selected': self.range_params == param_dict,
                    'query_string': cl.get_query_string(
                                        param_dict, [self.field_generic]),
                    'display': title,
                }
    return RangeFieldListFilter
 | 
More like this
- Add Toggle Switch Widget to Django Forms by OgliariNatan 1 month, 4 weeks ago
 - get_object_or_none by azwdevops 5 months, 2 weeks ago
 - Mask sensitive data from logger by agusmakmun 7 months, 2 weeks ago
 - Template tag - list punctuation for a list of items by shapiromatron 1 year, 9 months ago
 - JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 1 year, 9 months ago
 
Comments
Please login first before commenting.