views.py 9.58 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
from rest_framework.permissions import IsAuthenticated
8
from rest_framework.decorators import list_route
9

Matheus Miranda's avatar
Matheus Miranda committed
10 11
from .models import (Course, CourseProfessor, CourseStudent, ProfessorMessage,
                     ProfessorMessageRead, Class, Lesson)
12 13
from .serializers import (CourseSerializer, BasicCourseProfessorSerializer,
                          ProfessorMessageSerializer, ProfessorMessageReadSerializer,
Matheus Miranda's avatar
Matheus Miranda committed
14 15
                          LessonSerializer)

16

17 18
from courses.workspaces.serializers import CourseGroupSerializer

19 20 21 22 23
from .permissions import (
    IsProfessorCoordinatorOrAdminPermissionOrReadOnly,
    IsAssistantOrCoordinatorOrAdminOrRecipient,
    IsAdminOrReadOnly,
)
24

Matheus Miranda's avatar
Matheus Miranda committed
25

26
class CourseGroupViewSet(viewsets.ModelViewSet):
Matheus Miranda's avatar
Matheus Miranda committed
27

28 29 30 31 32 33 34 35 36 37
    model = Course
    queryset = Course.objects.all()
    serializer_class = CourseGroupSerializer

    def get_queryset(self):
        queryset = super(CourseGroupViewSet, self).get_queryset()
        course = self.request.query_params.get('id', None)

        if course:
            queryset = queryset.filter(groups__id = course)
Matheus Miranda's avatar
Matheus Miranda committed
38

39 40
        return queryset

41 42 43 44 45 46 47 48 49 50 51 52

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()
53 54

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

57
        if not self.request.user.is_superuser:
Bruno Martin's avatar
Bruno Martin committed
58
            role = self.request.query_params.get('role', None)
59 60 61 62 63 64
            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
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
            # 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')
81 82 83 84 85 86 87 88 89 90 91 92 93 94

        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
95
        data = super().metadata(request)
96 97 98
        if data.get('actions'):
            data.get('actions').get('POST').get('status').update({'choices': dict(Course.STATES[1:])})
        return data
99 100


101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
class MyCoursesViewSet(viewsets.ModelViewSet):
    model = Course
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly,)

    def get_queryset(self):
        queryset = super(MyCoursesViewSet, self).get_queryset()
        user = self.request.user
        course_students = CourseStudent.objects.filter(user__id=user.id).prefetch_related('course')
        courses_id = list(course_students.values_list('course__id', flat=True))
        queryset = self.queryset.filter(id__in=courses_id)

        return queryset


Matheus Miranda's avatar
Matheus Miranda committed
117 118 119 120 121 122 123 124
class CourseBySlugViewSet(viewsets.ModelViewSet):
    model = Course
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsAuthenticated,)
    lookup_field = 'slug'


125 126 127 128 129 130 131 132 133 134 135 136 137 138
class BaseCourseProfessorViewSet(viewsets.ModelViewSet):

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


139 140
class ProfessorMessageViewSet(viewsets.ModelViewSet):
    model = ProfessorMessage
141 142
    queryset = ProfessorMessage.objects.all()
    filter_fields = ('course', 'classrooms')
143
    serializer_class = ProfessorMessageSerializer
144
    permission_classes = (IsAssistantOrCoordinatorOrAdminOrRecipient,)
145 146

    def perform_create(self, serializer):
147
        classes = serializer.context['request'].data.get('classes', None)
148
        recipients = serializer.context['request'].data.get('users', None)
149
        classrooms = serializer.context['request'].data.get('classroom', None)
150

151 152
        users_to_be_added = []
        User = get_user_model()
153

154
        # Otherwise, user the recipients list
155
        if recipients:
156 157
            for user_id in serializer.context['request'].data['users']:
                users_to_be_added.append(User.objects.get(id=user_id))
158 159 160 161 162
        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)
163 164 165 166
        elif classrooms:
            for classrooms_id in classrooms:
                classrooms = Classrooms.objects.get(id=classrooms_id)
                users_to_be_added = classrooms.group.user_set.all()
167 168

        obj = serializer.save(professor=self.request.user, users=users_to_be_added)
169 170 171 172
        if obj:
            obj.send()

    def get_queryset(self):
173 174 175 176 177 178 179 180 181 182 183 184
        queryset = super().get_queryset()

        query = Q(
            Q(users=self.request.user)
            | Q(groups__in=self.request.user.groups.all())
            | Q(professor=self.request.user)
        )
        queryset = queryset.filter(query).order_by('-id').distinct()

        classroom = self.request.query_params.get('classroom', None)
        if classroom:
            queryset = queryset.filter(classrooms=classroom)
185 186 187 188 189 190 191 192 193 194

        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)]

195
        return queryset.prefetch_related('classrooms', 'classes', 'users', 'groups',).select_related('course', 'professor')
Matheus Miranda's avatar
Matheus Miranda committed
196

197 198 199 200
    @list_route(methods=['get'], permission_classes=[IsAssistantOrCoordinatorOrAdminOrRecipient])
    def count_message(self, request):
        messages = self.get_queryset()
        return Response({'count': messages.count()})
201 202


203 204 205 206 207
class ProfessorGlobalMessageViewSet(ProfessorMessageViewSet):
    """
    This view creates ProfessorMessages targeting specific users and with no ties to any course
    Only site admins can create messages using this endpoint
    """
208
    model = ProfessorMessage
209
    serializer_class = ProfessorMessageSerializer
210 211
    permission_classes = (IsAdminOrReadOnly,)

212 213 214
    def perform_create(self, serializer):
        User = get_user_model()
        users_to_be_added = []
Matheus Miranda's avatar
Matheus Miranda committed
215

216 217 218
        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)
219 220 221 222

        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()
223 224 225 226 227 228 229 230
                # 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))

231 232 233 234
        obj = serializer.save(professor=self.request.user, users=users_to_be_added)
        if obj:
            obj.send()

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

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
Matheus Miranda's avatar
Matheus Miranda committed
258 259 260 261 262 263 264 265 266 267 268 269


class LessonViewSet(viewsets.ModelViewSet):
    model = Lesson
    queryset = Lesson.objects.all()
    serializer_class = LessonSerializer
    ordering = ('position',)

    def get_queryset(self):
        queryset = super(LessonViewSet, self).get_queryset()
        course_id = self.kwargs['course_id']
        return queryset.filter(status='published', course_id=course_id)