admin.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. from django.contrib.admin import FieldListFilter
  2. from django.contrib.admin.options import IncorrectLookupParameters
  3. from django.core.exceptions import ValidationError
  4. from django.db.models import F
  5. from django.utils.translation import gettext_lazy as _
  6. from bitfield import Bit
  7. from bitfield.compat import bitor
  8. class BitFieldListFilter(FieldListFilter):
  9. def __init__(self, field, request, params, model, model_admin, field_path):
  10. self.lookup_kwarg = field_path
  11. self.lookup_val = int(request.GET.get(self.lookup_kwarg, 0))
  12. self.flags = field.flags
  13. self.labels = field.labels
  14. super().__init__(field, request, params, model, model_admin, field_path)
  15. def queryset(self, request, queryset):
  16. _filter = {p: bitor(F(p), v) for p, v in self.used_parameters.items()}
  17. try:
  18. return queryset.filter(**_filter)
  19. except ValidationError as e:
  20. raise IncorrectLookupParameters(e)
  21. def expected_parameters(self):
  22. return [self.lookup_kwarg]
  23. def choices(self, cl):
  24. yield {
  25. "selected": self.lookup_val == 0,
  26. "query_string": cl.get_query_string({}, [self.lookup_kwarg]),
  27. "display": _("All"),
  28. }
  29. for number, flag in enumerate(self.flags):
  30. bit_mask = Bit(number).mask
  31. yield {
  32. "selected": self.lookup_val == bit_mask,
  33. "query_string": cl.get_query_string({self.lookup_kwarg: bit_mask}),
  34. "display": self.labels[number],
  35. }