You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

281 lines
9.8 KiB

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