Coverage for website/members/api/v2/filters.py: 26.42%

43 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2025-08-14 10:31 +0000

1from datetime import datetime 

2 

3from django.db.models import Q 

4from django.utils import timezone 

5 

6from rest_framework import filters, serializers 

7 

8from members.models import Membership 

9 

10 

11class StartingYearFilter(filters.BaseFilterBackend): 

12 """Allows you to filter by starting year.""" 

13 

14 def filter_queryset(self, request, queryset, view): 

15 starting_year = request.query_params.get("starting_year", None) 

16 

17 if starting_year: 

18 queryset = queryset.filter(profile__starting_year=starting_year) 

19 

20 return queryset 

21 

22 def get_schema_operation_parameters(self, view): 

23 return [ 

24 { 

25 "name": "starting_year", 

26 "required": False, 

27 "in": "query", 

28 "description": "Filter by starting year", 

29 "schema": { 

30 "type": "number", 

31 }, 

32 } 

33 ] 

34 

35 

36class FormerMemberFilter(filters.BaseFilterBackend): 

37 def filter_queryset(self, request, queryset, view): 

38 former = request.query_params.get("former", "false") 

39 

40 if former == "false": 

41 # Filter out former members 

42 return ( 

43 queryset.exclude(membership=None) 

44 .filter( 

45 Q(membership__until__isnull=True) 

46 | Q(membership__until__gt=timezone.now().date()) 

47 ) 

48 .distinct() 

49 ) 

50 elif former == "true": 

51 # Filter out current members 

52 

53 memberships_query = Q(until__gt=datetime.now()) | Q(until=None) 

54 members_query = ~Q(id=None) 

55 

56 # Filter out all current active memberships 

57 memberships_query &= Q(type=Membership.MEMBER) | Q(type=Membership.HONORARY) 

58 memberships = Membership.objects.filter(memberships_query) 

59 members_query &= ~Q(pk__in=memberships.values("user__pk")) 

60 

61 memberships_query = Q(type=Membership.MEMBER) | Q(type=Membership.HONORARY) 

62 memberships = Membership.objects.filter(memberships_query) 

63 all_memberships = Membership.objects.all() 

64 # Only keep members that were once members, or are legacy users 

65 # that do not have any memberships at all 

66 members_query &= Q(pk__in=memberships.values("user__pk")) | ~Q( 

67 pk__in=all_memberships.values("user__pk") 

68 ) 

69 

70 return queryset.filter(members_query) 

71 elif former == "any": 

72 # Include both former and current members 

73 return queryset 

74 else: 

75 raise serializers.ValidationError("invalid former parameter") 

76 

77 def get_schema_operation_parameters(self, view): 

78 return [ 

79 { 

80 "name": "former", 

81 "required": False, 

82 "in": "query", 

83 "description": "Include former members or only former members", 

84 "schema": { 

85 "type": "string", 

86 "enum": ["true", "false", "any"], 

87 }, 

88 } 

89 ] 

90 

91 

92class MembershipTypeFilter(filters.BaseFilterBackend): 

93 """Allows you to filter by membership type.""" 

94 

95 def filter_queryset(self, request, queryset, view): 

96 membership_type = request.query_params.get("membership_type", None) 

97 

98 if membership_type: 

99 memberships = Membership.objects.filter(type=membership_type) 

100 queryset = queryset.filter(pk__in=memberships.values("user__pk")) 

101 

102 return queryset 

103 

104 def get_schema_operation_parameters(self, view): 

105 return [ 

106 { 

107 "name": "membership_type", 

108 "required": False, 

109 "in": "query", 

110 "description": "Filter by membership type", 

111 "schema": { 

112 "type": "string", 

113 }, 

114 } 

115 ]