Source code for members.api.viewsets
"""DRF viewsets defined by the members package"""
import copy
from rest_framework import permissions
from rest_framework import viewsets, filters, mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from members.api.serializers import (
MemberBirthdaySerializer,
MemberListSerializer,
ProfileRetrieveSerializer,
ProfileEditSerializer,
)
from members.models import Member
from utils.snippets import extract_date_range
[docs]class MemberViewset(viewsets.ReadOnlyModelViewSet, mixins.UpdateModelMixin):
"""Viewset that renders or edits a member"""
queryset = Member.objects.all()
filter_backends = (
filters.OrderingFilter,
filters.SearchFilter,
)
ordering_fields = ("profile__starting_year", "first_name", "last_name")
search_fields = ("profile__nickname", "first_name", "last_name", "username")
lookup_field = "pk"
[docs] def get_serializer_class(self):
if self.action == "retrieve":
if self.is_self_reference() or self.request.user.has_perm(
"members.change_profile"
):
return ProfileEditSerializer
return ProfileRetrieveSerializer
elif self.action.endswith("update"):
return ProfileEditSerializer
return MemberListSerializer
[docs] def get_queryset(self):
if self.action == "list":
return Member.current_members.get_queryset()
return Member.objects.all()
[docs] def is_self_reference(self):
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
lookup_arg = self.kwargs.get(lookup_url_kwarg)
return self.request.user.is_authenticated and lookup_arg in (
"me",
str(self.request.member.pk),
)
[docs] def get_permissions(self):
if self.action and (
not self.action.endswith("update") or self.is_self_reference()
):
return [permissions.IsAuthenticated()]
else:
return [permissions.DjangoModelPermissions()]
[docs] def get_object(self):
if self.is_self_reference():
return self.request.member.profile
else:
return super().get_object().profile
def _get_birthdays(self, member, start, end):
birthdays = []
start_year = max(start.year, member.profile.birthday.year)
for year in range(start_year, end.year + 1):
bday = copy.deepcopy(member)
try:
bday.profile.birthday = bday.profile.birthday.replace(year=year)
except ValueError as e:
if bday.profile.birthday.month == 2 and bday.profile.birthday.day == 29:
bday.profile.birthday = bday.profile.birthday.replace(
year=year, day=28
)
else:
raise e
if start.date() <= bday.profile.birthday <= end.date():
birthdays.append(bday)
return birthdays
[docs] @action(detail=False)
def birthdays(self, request):
start, end = extract_date_range(request)
queryset = Member.current_members.with_birthdays_in_range(start, end).filter(
profile__show_birthday=True
)
all_birthdays = [self._get_birthdays(m, start, end) for m in queryset.all()]
birthdays = [x for sublist in all_birthdays for x in sublist]
serializer = MemberBirthdaySerializer(birthdays, many=True)
return Response(serializer.data)