diff --git a/lms/app/admin.py b/lms/app/admin.py index d600a86..70cceae 100644 --- a/lms/app/admin.py +++ b/lms/app/admin.py @@ -10,13 +10,13 @@ class CourseAdmin(admin.ModelAdmin): @admin.register(Module) class ModuleAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'course', 'order') + list_display = ('id', 'title', 'course') search_fields = ('title', 'course__title') list_filter = ('course',) @admin.register(Lesson) class LessonAdmin(admin.ModelAdmin): - list_display = ('title', 'module', 'order') + list_display = ('title', 'module') search_fields = ('title', 'module__title') list_filter = ('module',) diff --git a/lms/app/migrations/0010_remove_lesson_order_remove_module_order.py b/lms/app/migrations/0010_remove_lesson_order_remove_module_order.py new file mode 100644 index 0000000..c5ca757 --- /dev/null +++ b/lms/app/migrations/0010_remove_lesson_order_remove_module_order.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.10 on 2025-01-14 17:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0009_lesson_description_alter_module_description'), + ] + + operations = [ + migrations.RemoveField( + model_name='lesson', + name='order', + ), + migrations.RemoveField( + model_name='module', + name='order', + ), + ] diff --git a/lms/app/models.py b/lms/app/models.py index 6bae408..6bb3bcf 100644 --- a/lms/app/models.py +++ b/lms/app/models.py @@ -35,7 +35,6 @@ class Module(models.Model): title = models.CharField(max_length=255, verbose_name="Module Title") description = models.TextField(null=True, verbose_name="Module Description") course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='modules', verbose_name="Course") - order = models.PositiveIntegerField(default=0, verbose_name="Order", unique=True) created_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="Created By") def str(self): @@ -48,7 +47,6 @@ class Lesson(models.Model): description = models.TextField(null=True, verbose_name="Lesson Description") content = models.TextField(verbose_name="Lesson Content") module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='lessons', verbose_name="Module") - order = models.PositiveIntegerField(default=0, verbose_name="Order") file = models.FileField(upload_to='lesson_files/', null=True, blank=True, verbose_name="Attached File") created_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, verbose_name="Created By") diff --git a/lms/app/permissions.py b/lms/app/permissions.py index 3466866..39404c9 100644 --- a/lms/app/permissions.py +++ b/lms/app/permissions.py @@ -20,6 +20,9 @@ class IsOwnerOrReadOnly(BasePermission): case "LessonViewSet": return obj.created_by == request.user + + case "EnrollmentViewSet": + return obj.student == request.user diff --git a/lms/app/serializers.py b/lms/app/serializers.py index 84e5923..8428be6 100644 --- a/lms/app/serializers.py +++ b/lms/app/serializers.py @@ -24,20 +24,21 @@ class LessonSerializer(serializers.ModelSerializer): class Meta: model = Lesson - fields = ['id', 'title', 'description', 'content', 'module', 'order', 'file'] + fields = ['id', 'title', 'description', 'content', 'module', 'file'] class ModuleSerializer(serializers.ModelSerializer): lessons = serializers.SerializerMethodField() class Meta: model = Module - fields = ['id', 'title', 'description', 'lessons', 'course', 'order'] + fields = ['id', 'title', 'description', 'lessons', 'course'] read_only_fields = ['course', 'lessons'] def get_lessons(self, obj): return obj.lessons.values('id', 'title', 'description') + class EnrollmentSerializer(serializers.ModelSerializer): course_details = serializers.SerializerMethodField() class Meta: diff --git a/lms/app/signals.py b/lms/app/signals.py new file mode 100644 index 0000000..e09f093 --- /dev/null +++ b/lms/app/signals.py @@ -0,0 +1,3 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver +from .model import Module diff --git a/lms/app/views.py b/lms/app/views.py index 9bb8ca7..5e79055 100644 --- a/lms/app/views.py +++ b/lms/app/views.py @@ -55,7 +55,7 @@ class ModuleViewSet(ModelViewSet): if course_id: course = Course.objects.filter(id=course_id).first() if course: - return Module.objects.filter(course=course).order_by('order') + return Module.objects.filter(course=course) return Module.objects.none() @@ -65,6 +65,10 @@ class ModuleViewSet(ModelViewSet): """ course_id = self.request.data.get('course') course = Course.objects.filter(id=course_id, owner=self.request.user).first() + is_owner = course.owner == self.request.user + if not is_owner: + raise PermissionDenied("You do not have permission to create module.") + if not course: return Response( {"detail": "This course not found."}, @@ -108,9 +112,26 @@ class LessonViewSet(ModelViewSet): is_enrolled = Enrollment.objects.filter(course=module.course, student=self.request.user).exists() if is_owner or is_enrolled: + return Lesson.objects.filter(id=lesson_id) # Return the lesson if the user is authorized return Lesson.objects.none() # Deny access if the user is not authorized + + def perform_create(self, serializer): + """ + Customize the creation of a lesson to include the module and the user who created it. + """ + module_id = self.request.data.get('module') # Get the module ID from the request + module = Module.objects.filter(id=module_id).first() # Fetch the module + is_owner = module.course.owner == self.request.user + if not is_owner: + raise PermissionDenied("You do not have permission to create lessons in this module.") + + if not module: + raise serializers.ValidationError({"module": "Module does not exist."}) + + # Save the lesson with the module and created_by user + serializer.save(module=module, created_by=self.request.user) @@ -120,10 +141,10 @@ class EnrollmentViewSet(ModelViewSet): permission_classes = [IsAuthenticated] http_method_names = ['get', 'post', 'delete'] - def retrieve(self, request, *args, **kwargs): - instance = Enrollment.objects.filter(user=request.user) + def list(self, request, *args, **kwargs): + instance = Enrollment.objects.filter(student=request.user) - serializer = self.get_serializer(instance) + serializer = self.get_serializer(instance, many=True) return Response(serializer.data) @@ -147,15 +168,6 @@ class EnrollmentViewSet(ModelViewSet): serializer = self.get_serializer(enrollment) return Response(serializer.data, status=status.HTTP_201_CREATED) - def destroy(self, request, *args, **kwargs): - # Get the enrollment object to delete - enrollment = self.get_object() - if enrollment.student != request.user: - raise PermissionDenied("You do not have permission to delete this enrollment.") - - # Delete the enrollment - enrollment.delete() - return Response({"detail": "Enrollment deleted successfully"}, status=status.HTTP_204_NO_CONTENT) class QuizViewSet(ModelViewSet):