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

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

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


18
class MemberViewset(viewsets.ReadOnlyModelViewSet):
19
    queryset = Member.objects.all()
20
    permission_classes = (permissions.IsAuthenticated,)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    filter_backends = (filters.OrderingFilter,filters.SearchFilter,)
    ordering_fields = ('starting_year', 'user__first_name', 'user__last_name')
    search_fields = ('nickname', 'user__first_name',
                     'user__last_name', 'user__username')

    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':
            memberships = Membership.objects.filter(
                Q(until__gt=datetime.now()) | Q(until=None))
            return Member.objects.filter(user__in=memberships.values('user'))
        return Member.objects.all()
37
38
39
40
41
42
43

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

        start_year = max(start.year, member.birthday.year)
        for year in range(start_year, end.year + 1):
            bday = copy.deepcopy(member)
44
45
46
47
48
49
50
            try:
                bday.birthday = bday.birthday.replace(year=year)
            except ValueError as e:
                if bday.birthday.month == 2 and bday.birthday.day == 29:
                    bday.birthday = bday.birthday.replace(year=year, day=28)
                else:
                    raise e
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
            if start.date() <= bday.birthday <= end.date():
                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')
            )
        except:
            raise ParseError(detail='start or end query parameters invalid')

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

        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)
83
84

    @list_route()
85
    def me(self, request):
86
        serializer = self.get_serializer_class()(request.user.member)
87
        return Response(serializer.data)