filters.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import django_filters
  2. from django.conf import settings
  3. from django.db.models import Q
  4. from extras.models import Tag
  5. class NumericInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
  6. """
  7. Filters for a set of numeric values. Example: id__in=100,200,300
  8. """
  9. pass
  10. class NullableCharFieldFilter(django_filters.CharFilter):
  11. """
  12. Allow matching on null field values by passing a special string used to signify NULL.
  13. """
  14. def filter(self, qs, value):
  15. if value != settings.FILTERS_NULL_CHOICE_VALUE:
  16. return super().filter(qs, value)
  17. qs = self.get_method(qs)(**{'{}__isnull'.format(self.field_name): True})
  18. return qs.distinct() if self.distinct else qs
  19. class TagFilter(django_filters.ModelMultipleChoiceFilter):
  20. """
  21. Match on one or more assigned tags. If multiple tags are specified (e.g. ?tag=foo&tag=bar), the queryset is filtered
  22. to objects matching all tags.
  23. """
  24. def __init__(self, *args, **kwargs):
  25. kwargs.setdefault('field_name', 'tags__slug')
  26. kwargs.setdefault('to_field_name', 'slug')
  27. kwargs.setdefault('conjoined', True)
  28. kwargs.setdefault('queryset', Tag.objects.all())
  29. super().__init__(*args, **kwargs)
  30. class NameSlugSearchFilterSet(django_filters.FilterSet):
  31. """
  32. A base class for adding the search method to models which only expose the `name` and `slug` fields
  33. """
  34. q = django_filters.CharFilter(
  35. method='search',
  36. label='Search',
  37. )
  38. def search(self, queryset, name, value):
  39. if not value.strip():
  40. return queryset
  41. return queryset.filter(
  42. Q(name__icontains=value) |
  43. Q(slug__icontains=value)
  44. )