views.py 7.25 KB
Newer Older
Bruno Martin's avatar
Bruno Martin committed
1
from django.db.models import Q
2
from django.db import IntegrityError
3
from django.contrib.auth import get_user_model
4 5

from rest_framework import viewsets, mixins
Bruno Martin's avatar
Bruno Martin committed
6
from rest_framework.response import Response
7 8
from rest_framework.permissions import IsAuthenticated

9
from .models import (Course, CourseProfessor, ProfessorMessage, ProfessorMessageRead, Class)
10 11 12
from .serializers import (CourseSerializer, BasicCourseProfessorSerializer,
                          ProfessorMessageSerializer, ProfessorMessageReadSerializer,
                          )
13

14
from .permissions import (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, IsAssistantOrCoordinatorOrReadOnly, IsAdminOrReadOnly)
15 16 17 18 19 20 21 22 23 24 25 26 27


class CourseViewSet(viewsets.ModelViewSet):

    model = Course
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    lookup_field = 'id'
    filter_fields = ('slug', 'home_published',)
    permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly,)

    def get_queryset(self):
        queryset = super(CourseViewSet, self).get_queryset()
28 29

        if not self.request.user.is_authenticated:
30
            return queryset.filter(is_public=True, status='published').prefetch_related('professors')
31

32
        if not self.request.user.is_superuser:
Bruno Martin's avatar
Bruno Martin committed
33
            role = self.request.query_params.get('role', None)
34 35 36 37 38 39
            if role:
                queryset = queryset.filter(
                    course_professors__role=role,
                    course_professors__user=self.request.user
                ).prefetch_related('professors')

Bruno Martin's avatar
Bruno Martin committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
            # Course must have status status published and (be public or share groups with user)
            query = Q(
                Q(status='published') & (
                    Q(is_public=True, ) | Q(groups__in=self.request.user.groups.all(), status='published')
                )
            )

            if (CourseProfessor.objects.filter(user=self.request.user, role='coordinator').exists()):
                query.add(Q(
                    course_professors__role='coordinator',
                    course_professors__user=self.request.user
                ), Q.OR)

            queryset = queryset.filter(query)

        queryset = queryset.prefetch_related('professors')
56 57 58 59 60 61 62 63 64 65 66 67 68 69

        return queryset.distinct()

    def post(self, request, **kwargs):
        course = self.get_object()
        serializer = CourseSerializer(course, request.data)

        if serializer.is_valid():
            serializer.save()
            return Response(status=200)
        else:
            return Response(serializer.errors, status=400)

    def metadata(self, request):
Bruno Martin's avatar
Bruno Martin committed
70
        data = super().metadata(request)
71 72 73
        if data.get('actions'):
            data.get('actions').get('POST').get('status').update({'choices': dict(Course.STATES[1:])})
        return data
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89


class BaseCourseProfessorViewSet(viewsets.ModelViewSet):

    model = CourseProfessor
    queryset = CourseProfessor.objects.all()
    # lookup_field = 'id'
    filter_fields = (
        'course',
        'user',
        'role',
    )
    serializer_class = BasicCourseProfessorSerializer
    permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, )


90 91 92 93 94 95 96 97
class ProfessorMessageViewSet(viewsets.ModelViewSet):
    model = ProfessorMessage
    lookup_field = 'id'
    filter_fields = ('course',)
    serializer_class = ProfessorMessageSerializer
    permission_classes = (IsAssistantOrCoordinatorOrReadOnly,)

    def perform_create(self, serializer):
98
        classes = serializer.context['request'].data.get('classes', None)
99
        recipients = serializer.context['request'].data.get('users', None)
100

101 102
        users_to_be_added = []
        User = get_user_model()
103

104
        # Otherwise, user the recipients list
105
        if recipients:
106 107
            for user_id in serializer.context['request'].data['users']:
                users_to_be_added.append(User.objects.get(id=user_id))
108 109 110 111 112
        elif classes:
            for class_id in classes:
                klass = Class.objects.get(id=class_id)
                for user in klass.students.all():
                    users_to_be_added.append(user.id)
113 114

        obj = serializer.save(professor=self.request.user, users=users_to_be_added)
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
        if obj:
            obj.send()

    def get_queryset(self):
        queryset = ProfessorMessage.objects.filter(users__in=[self.request.user]).order_by('-id')

        unread = self.request.query_params.get('unread', None)
        if unread:
            # Exclude read messages
            queryset = queryset.exclude(read_status__is_read=True, read_status__user=self.request.user)

        limit_to = self.request.query_params.get('limit_to', None)
        if limit_to:
            queryset = queryset[:int(limit_to)]

        return queryset

# This view creates ProfessorMessages targeting specific users and with no ties to any course
# Only site admins can create messages using this endpoint


class ProfessorGlobalMessageViewSet(mixins.CreateModelMixin,
                                    mixins.ListModelMixin,
                                    viewsets.GenericViewSet):
    model = ProfessorMessage
140
    serializer_class = ProfessorMessageSerializer
141 142
    permission_classes = (IsAdminOrReadOnly,)

143 144 145
    def perform_create(self, serializer):
        User = get_user_model()
        users_to_be_added = []
146 147 148 149
        
        all_students = serializer.context['request'].data.get('all_students', None)
        recipients = serializer.context['request'].data.get('users', None)
        groups = serializer.context['request'].data.get('groups', None)
150 151 152 153

        if all_students:
            # If all_students was set to True by the client, this is a global message
            users_to_be_added = User.objects.all()
154 155 156 157 158 159 160 161
                # If groups were specified, their users are the recipients
        elif groups:
            users_to_be_added = User.objects.filter(groups__in=groups)
        # Otherwise, user the recipients list
        elif recipients:
            for user_id in serializer.context['request'].data['users']:
                users_to_be_added.append(User.objects.get(id=user_id))

162 163 164 165
        obj = serializer.save(professor=self.request.user, users=users_to_be_added)
        if obj:
            obj.send()

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    def get_queryset(self):
        # Get all admin messages sent using this view
        queryset = ProfessorMessage.objects.filter(course=None).order_by('-id')

        limit_to = self.request.query_params.get('limit_to', None)
        if limit_to:
            queryset = queryset[:int(limit_to)]

        return queryset


class ProfessorMessageReadViewSet(viewsets.ModelViewSet):
    model = ProfessorMessageRead
    lookup_field = 'message'
    serializer_class = ProfessorMessageReadSerializer
    permission_classes = (IsAuthenticated,)

    def perform_create(self, serializer):
        try:
            read_info = serializer.save(user=self.request.user, is_read=True)
        except IntegrityError as e:
            read_info = ProfessorMessageRead.objects.get(message=self.request.data['message'], user=self.request.user)
            read_info.is_read = True
            read_info.save()

    def get_queryset(self):
        queryset = ProfessorMessageRead.objects.filter(user=self.request.user).order_by('-id')

        limit_to = self.request.query_params.get('limit_to', None)
        if limit_to:
            queryset = queryset[:int(limit_to)]

        return queryset