1import six 2 3from django.core.exceptions import ValidationError 4from django.utils.translation import ugettext_lazy as _ 5from django.contrib.admin import FieldListFilter 6from django.contrib.admin.options import IncorrectLookupParameters 7 8from bitfield import Bit, BitHandler 9 10 11class BitFieldListFilter(FieldListFilter): 12 """ 13 BitField list filter. 14 """ 15 16 def __init__(self, field, request, params, model, model_admin, field_path): 17 self.lookup_kwarg = field_path 18 self.lookup_val = int(request.GET.get(self.lookup_kwarg, 0)) 19 self.flags = field.flags 20 self.labels = field.labels 21 super(BitFieldListFilter, self).__init__( 22 field, request, params, model, model_admin, field_path) 23 24 def queryset(self, request, queryset): 25 filter_kwargs = dict( 26 (p, BitHandler(v, ())) 27 for p, v in six.iteritems(self.used_parameters) 28 ) 29 if not filter_kwargs: 30 return queryset 31 try: 32 return queryset.filter(**filter_kwargs) 33 except ValidationError as e: 34 raise IncorrectLookupParameters(e) 35 36 def expected_parameters(self): 37 return [self.lookup_kwarg] 38 39 def choices(self, cl): 40 yield { 41 'selected': self.lookup_val == 0, 42 'query_string': cl.get_query_string({}, [self.lookup_kwarg]), 43 'display': _('All'), 44 } 45 for number, flag in enumerate(self.flags): 46 bit_mask = Bit(number).mask 47 yield { 48 'selected': self.lookup_val == bit_mask, 49 'query_string': cl.get_query_string({self.lookup_kwarg: bit_mask}), 50 'display': self.labels[number], 51 } 52