viewsets.py 3.18 KB
Newer Older
1
2
3
import copy
from datetime import datetime

4
from django.utils import timezone
5
6
from rest_framework import permissions
from rest_framework import viewsets, filters
7
8
9
from rest_framework.decorators import list_route
from rest_framework.exceptions import ParseError
from rest_framework.response import Response
10
from pytz.exceptions import InvalidTimeError
11

12
13
14
from members.api.serializers import (MemberBirthdaySerializer,
                                     MemberRetrieveSerializer,
                                     MemberListSerializer)
15
from members.models import Member
16
17


18
class MemberViewset(viewsets.ReadOnlyModelViewSet):
19
    queryset = Member.objects.all()
20
    permission_classes = (permissions.IsAuthenticated,)
21
    filter_backends = (filters.OrderingFilter, filters.SearchFilter,)
22
23
24
25
    ordering_fields = ('profile__starting_year', 'first_name', 'last_name')
    search_fields = ('profile__nickname', 'first_name', 'last_name',
                     'username')
    lookup_field = 'pk'
26
27
28
29
30
31
32
33

    def get_serializer_class(self):
        if self.action == 'retrieve' or self.action == 'me':
            return MemberRetrieveSerializer
        return MemberListSerializer

    def get_queryset(self):
        if self.action == 'list':
34
            return Member.active_members.get_queryset()
35
        return Member.objects.all()
36
37
38
39

    def _get_birthdays(self, member, start, end):
        birthdays = []

40
        start_year = max(start.year, member.profile.birthday.year)
41
42
        for year in range(start_year, end.year + 1):
            bday = copy.deepcopy(member)
43
            try:
44
45
                bday.profile.birthday = \
                        bday.profile.birthday.replace(year=year)
46
            except ValueError as e:
47
48
49
50
                if (bday.profile.birthday.month == 2 and
                        bday.profile.birthday.day == 29):
                    bday.profile.birthday = \
                            bday.profile.birthday.replace(year=year, day=28)
51
52
                else:
                    raise e
53
            if start.date() <= bday.profile.birthday <= end.date():
54
55
56
57
58
59
60
61
62
63
64
65
66
                birthdays.append(bday)

        return birthdays

    @list_route()
    def birthdays(self, request):
        try:
            start = timezone.make_aware(
                datetime.strptime(request.query_params['start'], '%Y-%m-%d')
            )
            end = timezone.make_aware(
                datetime.strptime(request.query_params['end'], '%Y-%m-%d')
            )
67
68
69
        except (ValueError, KeyError, InvalidTimeError) as e:
            raise ParseError(
                detail='start or end query parameters invalid') from e
70
71

        queryset = (
72
73
            Member.active_members
                  .with_birthdays_in_range(start, end)
74
                  .filter(profile__show_birthday=True)
75
76
77
78
79
80
81
82
83
84
        )

        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)
85
86

    @list_route()
87
    def me(self, request):
88
        serializer = self.get_serializer_class()(request.member)
89
        return Response(serializer.data)