Adds filtering by ranges of values in the admin filter sidebar. This allows rows in numerical fields to be grouped together (in this case, group by price):
By store price
All
< 100
100 - 200
200 - 500
500 - 2000
>= 200
To use:
- save the code as rangevaluesfilterspec.py in your app's directory
- add
import rangevaluesfilterspec
to your models.py - add
myfield.list_filter_range = [value1, value2, ...]
to your filter field
Example:
from django.db import models
import rangevaluesfilterspec
class Product(models.Model):
store_price = models.DecimalField(max_digits=10, decimal_places=2)
store_price.list_filter_range = [100, 200, 500, 2000]
class Admin:
list_filter = ['store_price']
Note that two extra groups are added: less-than the lowest value, and greater-than-or-equal-to the highest value.
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 65 66 67 68 69 70 71 72 73 | # Author: wgollino ([email protected])
# File: rangevaluesfilterspec.py
#
# Adds filtering by ranges of values in the admin filter sidebar. The example below results in this filter:
#
# By store price
# All
# < 100
# 100 - 200
# 200 - 500
# 500 - 2000
# >= 200
#
#
# Example:
#
# from django.db import models
# import rangevaluesfilterspec
#
# class Product(models.Model):
# store_price = models.DecimalField(max_digits=10, decimal_places=2)
# store_price.list_filter_range = [100, 200, 500, 2000]
#
# class Admin:
# list_filter = ['store_price']
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from django.contrib.admin.filterspecs import FilterSpec
class RangeValuesFilterSpec(FilterSpec):
"""
Adds filtering by ranges of values in the admin filter sidebar.
Set range split points in the model field attribute 'list_filter_range'.
my_model_field.list_filter_range = [100, 200, 300]
Will define the ranges:
my_model_field < 100
my_model_field >= 100 AND my_model_field < 200
my_model_field >= 200 AND my_model_field < 300
my_model_field >= 300
"""
def __init__(self, f, request, params, model):
super(RangeValuesFilterSpec, self).__init__(f, request, params, model)
self.field_generic = '%s__' % self.field.name
self.parsed_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])
self.links = [(_('All'), {})]
last_value = None
for max_value in sorted(f.list_filter_range):
max_value = str(max_value)
if last_value == None:
label = '< ' + max_value
range = {'%s__lt' % f.name: max_value}
else:
label = last_value + ' - ' + max_value
range = {'%s__gte' % self.field.name: last_value, '%s__lt' % f.name: max_value}
self.links.append((_(mark_safe(label)), range))
last_value = max_value
self.links.append((_(mark_safe('≥ ' + max_value)), {'%s__gte' % f.name: max_value}))
def choices(self, cl):
for title, param_dict in self.links:
yield {'selected': self.parsed_params == param_dict,
'query_string': cl.get_query_string(param_dict, [self.field_generic]),
'display': title}
# register the filter before the default filter
FilterSpec.filter_specs.insert(-1, (lambda f: hasattr(f, 'list_filter_range'), RangeValuesFilterSpec))
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
hanks! with a little updating (FilterSpec now passes model_admin as 6th parameter) works just as advertised.
#
just to make it clear... you need to change these lines:
` ......
....... `
#
Please login first before commenting.