import django_filters from django.db.models import Q from collections import OrderedDict from django.contrib.auth.models import User from generic.models import CidUser, Examination, Supervisor, UserGrades class CidUserFilter(django_filters.FilterSet): active = django_filters.BooleanFilter( field_name="active", label="CID active", initial=True ) class Meta: model = CidUser # fields = ("cid", "active", "internal_candidate", "group") fields = { "cid": ["contains"], "active": ["exact"], "internal_candidate": ["exact"], "group": ["exact"], "group__name": ["contains"], "email": ["contains"], } @property def qs(self): parent = super().qs # filter_active = getattr(self.request, 'active', True) if "active" not in self.request.GET: return parent.filter(active=True) return parent class UserUserFilter(django_filters.FilterSet): # Generic search across name and email/username q = django_filters.CharFilter(method='filter_search', label='Search') userprofile__grade = django_filters.ModelChoiceFilter(queryset=UserGrades.objects.all(),label="Grade") userprofile__supervisor = django_filters.ModelChoiceFilter(queryset=Supervisor.objects.all(), label="Supervisor") userprofile__peninsula_trainee = django_filters.BooleanFilter(label="Peninsula Trainee") #has_supervisor = django_filters.BooleanFilter(field_name='supervisor', lookup_expr='isnull', exclude=True, label="Has Supervisor") class Meta: model = User # fields = ("cid", "active", "internal_candidate", "group") fields = { "first_name": ["icontains"], "last_name": ["icontains"], #"active": ["exact"], "user_groups": ["exact"], "user_groups__name": ["icontains"], #"userprofile__grade": ["exact"], #"userprofile__supervisor": ["exact"], "email": ["icontains"], "is_active": ["exact"], "groups": ["exact"], } @property def qs(self): parent = super().qs ## filter_active = getattr(self.request, 'active', True) if "is_active" not in self.request.GET: return parent.filter(is_active=True) return parent def __init__(self, *args, **kwargs): super(UserUserFilter, self).__init__(*args, **kwargs) self.form.initial['is_active'] = True def filter_search(self, queryset, name, value): """ Generic search that matches first name, last name, email or username. """ v = (value or "").strip() if not v: return queryset return queryset.filter( Q(first_name__icontains=v) | Q(last_name__icontains=v) | Q(email__icontains=v) | Q(username__icontains=v) ) def __post_init_reorder__(self): """Internal helper to move the generic search 'q' to the front of the form fields.""" try: fields = self.form.fields if 'q' in fields: new_order = ['q'] + [k for k in fields.keys() if k != 'q'] self.form.fields = OrderedDict((k, fields[k]) for k in new_order) except Exception: pass # Ensure reorder runs after initialization def __new__(cls, *args, **kwargs): instance = super(UserUserFilter, cls).__new__(cls) # attach a post-init hook to reorder form fields orig_init = instance.__init__ def wrapped_init(*a, **k): orig_init(*a, **k) try: instance.__post_init_reorder__() except Exception: pass instance.__init__ = wrapped_init return instance class ExaminationFilter(django_filters.FilterSet): class Meta: model = Examination fields = {"examination": ["icontains"], "modality": ["exact"]} def __init__( self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None, ): super(ExaminationFilter, self).__init__( data=data, queryset=queryset, prefix=prefix, request=request ) pass class SupervisorFilter(django_filters.FilterSet): class Meta: model = Supervisor fields = { "name": ["icontains"], "email": ["icontains"], "active": ["exact"], "site": ["exact"], } @property def qs(self): parent = super().qs if "active" not in self.request.GET: return parent.filter(active=True) return parent def __init__( self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None, ): super(SupervisorFilter, self).__init__( data=data, queryset=queryset, prefix=prefix, request=request ) pass