Coverage for website/members/api/v2/views.py: 78.57%
40 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1"""API views of the activemembers app."""
3from django.db.models import Prefetch, Q
4from django.shortcuts import get_object_or_404
5from django.utils import timezone
7from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
8from rest_framework import filters as framework_filters
9from rest_framework.generics import ListAPIView, RetrieveAPIView, UpdateAPIView
11from members.api.v2 import filters
12from members.api.v2.permissions import HasActiveMembership
13from members.api.v2.serializers.member import (
14 MemberCurrentSerializer,
15 MemberListSerializer,
16 MemberSerializer,
17)
18from members.models import Member, Membership
19from thaliawebsite.api.openapi import OAuthAutoSchema
20from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod
21from utils.media.services import fetch_thumbnails
24class MemberListView(ListAPIView):
25 """Returns an overview of all members."""
27 serializer_class = MemberListSerializer
29 def get_queryset(self):
30 today = timezone.now().date()
31 return (
32 Member.objects.all()
33 .select_related("profile")
34 .prefetch_related(
35 "membership_set",
36 Prefetch(
37 "membership_set",
38 queryset=Membership.objects.filter(
39 Q(until__isnull=True) | Q(until__gt=today), since__lte=today
40 ).order_by("-since")[:1],
41 to_attr="_current_membership",
42 ),
43 )
44 )
46 def get_serializer(self, *args, **kwargs):
47 if len(args) > 0:
48 members = args[0]
49 fetch_thumbnails([member.profile.photo for member in members])
50 return super().get_serializer(*args, **kwargs)
52 permission_classes = [IsAuthenticatedOrTokenHasScope, HasActiveMembership]
53 required_scopes = ["members:read"]
54 filter_backends = (
55 framework_filters.OrderingFilter,
56 framework_filters.SearchFilter,
57 filters.MembershipTypeFilter,
58 filters.StartingYearFilter,
59 filters.FormerMemberFilter,
60 )
61 ordering_fields = ("first_name", "last_name", "username")
62 search_fields = (
63 "profile__nickname",
64 "profile__starting_year",
65 "first_name",
66 "last_name",
67 "username",
68 )
71class MemberDetailView(RetrieveAPIView):
72 """Returns details of a member."""
74 serializer_class = MemberSerializer
75 queryset = Member.objects.all().prefetch_related(
76 "membergroupmembership_set", "mentorship_set"
77 )
78 permission_classes = [
79 IsAuthenticatedOrTokenHasScope,
80 HasActiveMembership,
81 ]
82 required_scopes = ["members:read"]
85class MemberCurrentView(MemberDetailView, UpdateAPIView):
86 """Returns details of the authenticated member."""
88 serializer_class = MemberCurrentSerializer
89 schema = OAuthAutoSchema(operation_id_base="CurrentMember")
90 permission_classes = [
91 IsAuthenticatedOrTokenHasScopeForMethod,
92 ]
93 required_scopes_per_method = {
94 "GET": ["profile:read"],
95 "PATCH": ["profile:write"],
96 "PUT": ["profile:write"],
97 }
99 def get_object(self):
100 return get_object_or_404(self.get_queryset(), pk=self.request.user.pk)