from django.db.models import Q from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.authentication import TokenAuthentication from rest_framework.decorators import action from rest_framework.response import Response from apps.course.models import ( Course, CourseCategory, CourseChapter, CourseLesson, Lesson, CourseAttachment, Attachment, CourseGlossary, Glossary, CourseLiveSession, LiveSessionUser, LiveSessionRecording ) from apps.course.serializers.admin import ( AdminCourseCategorySerializer, AdminCourseListSerializer, AdminCourseDetailSerializer, AdminCourseChapterSerializer, AdminCourseLessonSerializer, AdminCourseAttachmentSerializer, AdminCourseGlossarySerializer, AdminLessonSerializer, AdminGlossarySerializer, AdminAttachmentSerializer, AdminLiveSessionListSerializer, AdminLiveSessionDetailSerializer ) class AdminCourseViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course management. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] def get_serializer_class(self): if self.action == 'list': return AdminCourseListSerializer return AdminCourseDetailSerializer def get_queryset(self): queryset = Course.objects.all().select_related('category', 'professor') # Search Query search_query = self.request.query_params.get('search', None) if search_query: queryset = queryset.filter( Q(title__icontains=search_query) | Q(description__icontains=search_query) | Q(short_description__icontains=search_query) ) # Filters category_id = self.request.query_params.get('category', None) if category_id: queryset = queryset.filter(category_id=category_id) level = self.request.query_params.get('level', None) if level: queryset = queryset.filter(level=level) status_param = self.request.query_params.get('status', None) if status_param: queryset = queryset.filter(status=status_param) is_free_param = self.request.query_params.get('is_free', None) if is_free_param is not None: if is_free_param.lower() == 'true': queryset = queryset.filter(is_free=True) elif is_free_param.lower() == 'false': queryset = queryset.filter(is_free=False) return queryset.order_by('-id') class AdminChapterViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course Chapters. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminCourseChapterSerializer pagination_class = None def get_queryset(self): queryset = CourseChapter.objects.all() course_id = self.request.query_params.get('course', None) if course_id: queryset = queryset.filter(course_id=course_id) return queryset.order_by('priority', 'id') @action(detail=False, methods=['post']) def reorder(self, request): """ Reorders chapters in bulk. Format: {"chapter_ids": [id1, id2, ...]} """ chapter_ids = request.data.get('chapter_ids', []) if not chapter_ids: return Response({'error': 'chapter_ids list is required'}, status=400) from django.db import transaction with transaction.atomic(): for idx, c_id in enumerate(chapter_ids): CourseChapter.objects.filter(id=c_id).update(priority=idx + 1) return Response({'status': 'success'}) class AdminCourseLessonViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Lessons associated with a Course/Chapter. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminCourseLessonSerializer pagination_class = None def get_queryset(self): queryset = CourseLesson.objects.all().select_related('lesson', 'chapter') course_id = self.request.query_params.get('course', None) if course_id: queryset = queryset.filter(course_id=course_id) chapter_id = self.request.query_params.get('chapter', None) if chapter_id: queryset = queryset.filter(chapter_id=chapter_id) return queryset.order_by('priority', 'id') def perform_destroy(self, instance): # Prevent orphans: delete the base Lesson object along with the junction model lesson = instance.lesson instance.delete() if lesson: lesson.delete() @action(detail=False, methods=['post']) def reorder(self, request): """ Reorders lessons in bulk. Format: {"lesson_ids": [id1, id2, ...]} """ lesson_ids = request.data.get('lesson_ids', []) if not lesson_ids: return Response({'error': 'lesson_ids list is required'}, status=400) from django.db import transaction with transaction.atomic(): for idx, l_id in enumerate(lesson_ids): CourseLesson.objects.filter(id=l_id).update(priority=idx + 1) return Response({'status': 'success'}) class AdminCourseAttachmentViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course Attachments. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminCourseAttachmentSerializer pagination_class = None def get_queryset(self): queryset = CourseAttachment.objects.all().select_related('attachment') course_id = self.request.query_params.get('course', None) if course_id: queryset = queryset.filter(course_id=course_id) return queryset.order_by('-id') def perform_destroy(self, instance): # Prevent orphans: delete base Attachment along with junction model attachment = instance.attachment instance.delete() if attachment: attachment.delete() class AdminCourseGlossaryViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course Glossary terms. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminCourseGlossarySerializer pagination_class = None def get_queryset(self): queryset = CourseGlossary.objects.all().select_related('glossary') course_id = self.request.query_params.get('course', None) if course_id: queryset = queryset.filter(course_id=course_id) return queryset.order_by('-id') def perform_destroy(self, instance): # Prevent orphans: delete base Glossary along with junction model glossary = instance.glossary instance.delete() if glossary: glossary.delete() class AdminCourseCategoryViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course Categories. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminCourseCategorySerializer def get_queryset(self): queryset = CourseCategory.objects.all().order_by('-id') search = self.request.query_params.get('search', None) if search: queryset = queryset.filter(Q(name__icontains=search) | Q(slug__icontains=search)) return queryset class AdminLessonViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for base Lesson. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminLessonSerializer def get_queryset(self): queryset = Lesson.objects.all().order_by('-id') search = self.request.query_params.get('search', None) if search: queryset = queryset.filter(title__icontains=search) content_type = self.request.query_params.get('content_type', None) if content_type: queryset = queryset.filter(content_type=content_type) return queryset class AdminGlossaryViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for base Glossary. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminGlossarySerializer def get_queryset(self): queryset = Glossary.objects.all().order_by('-id') search = self.request.query_params.get('search', None) if search: queryset = queryset.filter(Q(title__icontains=search) | Q(description__icontains=search)) return queryset class AdminAttachmentViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for base Attachment. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] serializer_class = AdminAttachmentSerializer def get_queryset(self): queryset = Attachment.objects.all().order_by('-id') search = self.request.query_params.get('search', None) if search: queryset = queryset.filter(title__icontains=search) return queryset class AdminLiveSessionViewSet(viewsets.ModelViewSet): """ Admin CRUD ViewSet for Course Live Sessions. """ permission_classes = [IsAuthenticated, IsAdminUser] authentication_classes = [TokenAuthentication] def get_serializer_class(self): if self.action == 'list': return AdminLiveSessionListSerializer return AdminLiveSessionDetailSerializer def get_queryset(self): queryset = CourseLiveSession.objects.all().select_related('course') search = self.request.query_params.get('search', None) if search: queryset = queryset.filter( Q(subject__icontains=search) | Q(room_id__icontains=search) | Q(course__title__icontains=search) ) course_id = self.request.query_params.get('course', None) if course_id: queryset = queryset.filter(course_id=course_id) return queryset.order_by('-started_at')