from django.db.models import Q from django.db import IntegrityError from django.contrib.auth import get_user_model from rest_framework import viewsets, mixins from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework.decorators import list_route from .models import (Course, CourseProfessor, CourseStudent, ProfessorMessage, ProfessorMessageRead, Class, Lesson) from .serializers import (CourseSerializer, BasicCourseProfessorSerializer, ProfessorMessageSerializer, ProfessorMessageReadSerializer, LessonSerializer) from courses.workspaces.serializers import CourseGroupSerializer from .permissions import ( IsProfessorCoordinatorOrAdminPermissionOrReadOnly, IsAssistantOrCoordinatorOrAdminOrRecipient, IsAdminOrReadOnly, ) class CourseGroupViewSet(viewsets.ModelViewSet): 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) return queryset 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() if not self.request.user.is_authenticated: return queryset.filter(is_public=True, status='published').prefetch_related('professors') if not self.request.user.is_superuser: role = self.request.query_params.get('role', None) if role: queryset = queryset.filter( course_professors__role=role, course_professors__user=self.request.user ).prefetch_related('professors') # 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') # ) #) from django.utils.translation import get_language current_language = get_language() query = Q(status='published', lang__contains=[current_language]) 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') 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): data = super().metadata(request) if data.get('actions'): data.get('actions').get('POST').get('status').update({'choices': dict(Course.STATES[1:])}) return data 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 class CourseBySlugViewSet(viewsets.ModelViewSet): model = Course queryset = Course.objects.all() serializer_class = CourseSerializer permission_classes = (IsAuthenticated,) lookup_field = 'slug' class BaseCourseProfessorViewSet(viewsets.ModelViewSet): model = CourseProfessor queryset = CourseProfessor.objects.all() # lookup_field = 'id' filter_fields = ( 'course', 'user', 'role', ) serializer_class = BasicCourseProfessorSerializer permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, ) class ProfessorMessageViewSet(viewsets.ModelViewSet): model = ProfessorMessage queryset = ProfessorMessage.objects.all() filter_fields = ('course', 'classrooms') serializer_class = ProfessorMessageSerializer # permission_classes = (IsAssistantOrCoordinatorOrAdminOrRecipient) permission_classes = (IsAdminOrReadOnly, ) def perform_create(self, serializer): classes = serializer.context['request'].data.get('classes', None) recipients = serializer.context['request'].data.get('users', None) classrooms = serializer.context['request'].data.get('classroom', None) users_to_be_added = [] User = get_user_model() # Otherwise, user the recipients list if recipients: for user_id in serializer.context['request'].data['users']: users_to_be_added.append(User.objects.get(id=user_id)) 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) elif classrooms: for classrooms_id in classrooms: classrooms = Classrooms.objects.get(id=classrooms_id) users_to_be_added = classrooms.group.user_set.all() obj = serializer.save(professor=self.request.user, users=users_to_be_added) if obj: obj.send() def get_queryset(self): 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) 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.prefetch_related('classrooms', 'classes', 'users', 'groups',).select_related('course', 'professor') @list_route(methods=['get'], permission_classes=[IsAssistantOrCoordinatorOrAdminOrRecipient]) def count_message(self, request): messages = self.get_queryset() return Response({'count': messages.count()}) 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 """ model = ProfessorMessage serializer_class = ProfessorMessageSerializer permission_classes = (IsAdminOrReadOnly,) def perform_create(self, serializer): User = get_user_model() users_to_be_added = [] 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) 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() # 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)) obj = serializer.save(professor=self.request.user, users=users_to_be_added) if obj: obj.send() 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 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)