from rest_framework.generics import ListAPIView, RetrieveAPIView, GenericAPIView from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from django.shortcuts import get_object_or_404 from rest_framework import status from rest_framework.response import Response from apps.course.serializers import ( <<<<<<< HEAD LessonSerializer ) from apps.course.models import Course, Lesson, LessonCompletion ======= CourseLessonSerializer ) from apps.course.models import Course, CourseLesson, LessonCompletion >>>>>>> develop from apps.course.doc import * from utils.exceptions import AppAPIException from rest_framework.permissions import IsAuthenticated class LessonListView(ListAPIView): <<<<<<< HEAD serializer_class = LessonSerializer queryset = Lesson.objects.filter(is_active=True) @swagger_auto_schema( operation_description=doc_courses_lesson(), ======= serializer_class = CourseLessonSerializer @swagger_auto_schema( operation_description=doc_courses_lesson(), tags=['Imam-Javad - Course'], >>>>>>> develop ) def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) def get_queryset(self): <<<<<<< HEAD course_slug = self.kwargs.get('slug') course = get_object_or_404(Course, slug=course_slug) course = Course.objects.filter(slug=course_slug).first() if not course: raise AppAPIException({"message": "course not found"}, status_code=status.HTTP_404_NOT_FOUND) return self.queryset.filter(course=course).order_by('priority','id') ======= """ Optimized queryset with select_related and prefetch_related for lesson relationships """ course_slug = self.kwargs.get('slug') course = get_object_or_404(Course, slug=course_slug) return CourseLesson.objects.select_related( 'course', 'lesson' ).prefetch_related( 'completions', 'quizzes' ).filter( course=course, is_active=True ).order_by('priority', 'id') >>>>>>> develop class LessonDetailView(RetrieveAPIView): <<<<<<< HEAD serializer_class = LessonSerializer def get(self, request, *args, **kwargs): lesson_id = self.kwargs.get('id') lesson = get_object_or_404(Lesson, id=lesson_id, is_active=True) course = lesson.course lessons = Lesson.objects.filter(course=course, is_active=True).order_by('priority') total_lessons = lessons.count() current_lesson_number = list(lessons.values_list('id', flat=True)).index(lesson.id) + 1 next_lesson = lessons.filter(priority__gt=lesson.priority).order_by('priority').first() next_lesson_id = next_lesson.id if next_lesson else None previous_lesson = lessons.filter(priority__lt=lesson.priority).order_by('-priority').first() previous_lesson_id = previous_lesson.id if previous_lesson else None lesson_data = self.get_serializer(lesson).data ======= serializer_class = CourseLessonSerializer @swagger_auto_schema( operation_description="Get detailed lesson information with navigation data", tags=["Imam-Javad - Course"], manual_parameters=[ openapi.Parameter( 'id', openapi.IN_PATH, description="Lesson ID", type=openapi.TYPE_INTEGER, required=True ) ], responses={ 200: openapi.Response( description="Lesson details with navigation information", schema=CourseLessonSerializer() ) } ) def get(self, request, *args, **kwargs): """ Optimized lesson detail view with select_related for relationships """ lesson_id = self.kwargs.get('id') course_lesson = get_object_or_404( CourseLesson.objects.select_related('course', 'lesson'), id=lesson_id, is_active=True ) course = course_lesson.course lessons = CourseLesson.objects.select_related( 'lesson' ).filter( course=course, is_active=True ).order_by('priority') total_lessons = lessons.count() current_lesson_number = list(lessons.values_list('id', flat=True)).index(course_lesson.id) + 1 next_lesson = lessons.filter(priority__gt=course_lesson.priority).order_by('priority').first() next_lesson_id = next_lesson.id if next_lesson else None previous_lesson = lessons.filter(priority__lt=course_lesson.priority).order_by('-priority').first() previous_lesson_id = previous_lesson.id if previous_lesson else None lesson_data = self.get_serializer(course_lesson).data >>>>>>> develop lesson_data['total_lessons'] = total_lessons lesson_data['current_lesson_number'] = current_lesson_number lesson_data['next_lesson_id'] = next_lesson_id lesson_data['previous_lesson_id'] = previous_lesson_id lesson_data['can_go_next'] = next_lesson is not None <<<<<<< HEAD # # Get the next and previous lessons based on priority and id # next_lesson = Lesson.objects.filter( # course=lesson.course, # is_active=True, # priority__gte=lesson.priority, # id__gt=lesson.id # ).order_by('priority', 'id').first() # previous_lesson = Lesson.objects.filter( # course=lesson.course, # is_active=True, # priority__lte=lesson.priority, # id__lt=lesson.id # ).order_by('-priority', '-id').first() # total_lessons = Lesson.objects.filter(course=lesson.course, is_active=True).count() # # Calculate the current lesson number in the course # current_lesson_number = Lesson.objects.filter( # course=lesson.course, # is_active=True, # priority__lte=lesson.priority # ).count() # # Serialize the current lesson # lesson_data = self.get_serializer(lesson).data # # Add current lesson number and total lessons # lesson_data['current_lesson_number'] = current_lesson_number # lesson_data['total_lessons'] = total_lessons # # Add next and previous lesson ids # lesson_data['next_lesson_id'] = next_lesson.id if next_lesson else None # lesson_data['previous_lesson_id'] = previous_lesson.id if previous_lesson else None ======= >>>>>>> develop return Response(lesson_data) <<<<<<< HEAD class LessonCompletionCreateAPIView(GenericAPIView): permission_classes = [IsAuthenticated] @swagger_auto_schema( ======= class LessonCompletionToggleAPIView(GenericAPIView): permission_classes = [IsAuthenticated] @swagger_auto_schema( operation_description="Toggle lesson completion status (Check/Uncheck)", tags=["Imam-Javad - Course"], >>>>>>> develop request_body=openapi.Schema( type=openapi.TYPE_OBJECT, required=['lesson_id'], properties={ <<<<<<< HEAD 'lesson_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='ID of the lesson to be marked as completed'), }, ), responses={ 201: 'Lesson completed successfully.', 200: 'Lesson already completed.', ======= 'lesson_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='ID of the lesson to toggle'), }, ), responses={ 201: 'Lesson marked as COMPLETED.', 200: 'Lesson marked as INCOMPLETE (Unchecked).', >>>>>>> develop 400: 'Lesson ID is required.', 404: 'Lesson not found.', } ) def post(self, request): <<<<<<< HEAD student = request.user # Assuming the user is the student ======= student = request.user >>>>>>> develop lesson_id = request.data.get('lesson_id') if not lesson_id: return Response({'error': 'Lesson ID is required.'}, status=status.HTTP_400_BAD_REQUEST) <<<<<<< HEAD try: lesson = Lesson.objects.get(id=lesson_id) except Lesson.DoesNotExist: return Response({'error': 'Lesson not found.'}, status=status.HTTP_404_NOT_FOUND) # Check if the lesson is already completed by the student if LessonCompletion.objects.filter(student=student, lesson=lesson).exists(): return Response({'message': 'Lesson already completed.'}, status=status.HTTP_200_OK) # Create a new completion record completion = LessonCompletion(student=student, lesson=lesson) completion.save() return Response({'message': 'Lesson completed successfully.'}, status=status.HTTP_201_CREATED) ======= try: course_lesson = CourseLesson.objects.get(id=lesson_id) except CourseLesson.DoesNotExist: return Response({'error': 'Lesson not found.'}, status=status.HTTP_404_NOT_FOUND) # TOGGLE LOGIC # Try to find an existing completion record completion = LessonCompletion.objects.filter(student=student, course_lesson=course_lesson).first() if completion: # Scenario: The user clicked by mistake or wants to un-check # Action: Delete the record completion.delete() return Response( {'message': 'Lesson marked as incomplete.', 'is_completed': False}, status=status.HTTP_200_OK ) else: # Scenario: The lesson is not finished yet # Action: Create the record LessonCompletion.objects.create(student=student, course_lesson=course_lesson) return Response( {'message': 'Lesson completed successfully.', 'is_completed': True}, status=status.HTTP_201_CREATED ) >>>>>>> develop