Skip to content

Commit 6659402

Browse files
EthanZ23cj-ballesteros
authored andcommitted
Implemented Solution model endpoint views.py, serializers.py, & urls.py
1 parent eb6a098 commit 6659402

File tree

3 files changed

+103
-10
lines changed

3 files changed

+103
-10
lines changed

backend/apps/lessons/serializers.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from rest_framework import serializers
2-
from .models import Assignment, Quiz, Question, Choice
2+
from .models import Assignment, Quiz, Question, Choice, Solution
33

44

55
class AssignmentSerializer(serializers.ModelSerializer):
@@ -35,4 +35,10 @@ class Meta:
3535
class ChoiceSerializer(serializers.ModelSerializer):
3636
class Meta:
3737
model = Choice
38-
fields = ["id", "question", "choice_text", "is_correct"]
38+
fields = ["id", "question", "choice_text", "is_correct"]
39+
40+
41+
class SolutionSerializer(serializers.ModelSerializer):
42+
class Meta:
43+
model = Solution
44+
fields = ["id", "question", "choices", "short_answer_text"]

backend/apps/lessons/urls.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
AssignmentCreateView,
55
QuizListCreateView,
66
QuizDetailView,
7-
QuizQuestionListView,
7+
QQuestionListView,
88
QuestionCreateView,
99
QuestionUpdateView,
1010
QuestionDeleteView,
1111
ChoiceListView,
1212
ChoiceCreateView,
1313
ChoiceUpdateView,
14-
ChoiceDeleteView
14+
ChoiceDeleteView,
15+
SolutionDetailView,
16+
SolutionCreateView,
17+
SolutionUpdateView,
18+
SolutionDeleteView
1519
)
1620

1721
urlpatterns = [
@@ -27,7 +31,7 @@
2731
QuizDetailView.as_view(), name="quiz-detail"),
2832
# - QUIZ Questions
2933
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/",
30-
QuizQuestionListView.as_view(), name="quiz-question-list"),
34+
QQuestionListView.as_view(), name="quiz-question-list"),
3135
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/create/",
3236
QuestionCreateView.as_view(), name="question-create"),
3337
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/update/",
@@ -43,5 +47,15 @@
4347
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/choices/update/",
4448
ChoiceUpdateView.as_view(), name="choice-update"),
4549
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/choices/delete/",
46-
ChoiceDeleteView.as_view(), name="choice-delete")
50+
ChoiceDeleteView.as_view(), name="choice-delete"),
51+
52+
# CRUD endpoints for Solutions
53+
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/solution/",
54+
SolutionDetailView.as_view(), name="solution-detail"),
55+
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/solution/create/",
56+
SolutionCreateView.as_view(), name="solution-create"),
57+
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/solution/update/",
58+
SolutionUpdateView.as_view(), name="solution-update"),
59+
path("assignments/<int:assignment_id>/quiz/<int:quiz_id>/questions/<int:question_id>/solution/delete/",
60+
SolutionDeleteView.as_view(), name="solution-delete")
4761
]

backend/apps/lessons/views.py

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from rest_framework import status
55
from rest_framework.permissions import IsAuthenticated, IsAdminUser
66
from .permissions import IsAdminOrTutor
7-
from .models import Assignment, Quiz, Question, Choice
8-
from .serializers import AssignmentSerializer, QuizSerializer, QuestionSerializer, ChoiceSerializer
7+
from .models import Assignment, Quiz, Question, Choice, Solution
8+
from .serializers import AssignmentSerializer, QuizSerializer, QuestionSerializer, ChoiceSerializer, SolutionSerializer
99

1010

1111
# - Assignments:
@@ -130,10 +130,11 @@ def delete(self, request, assignment_id, quiz_id):
130130
quiz = self.get_object(assignment_id, quiz_id)
131131
quiz.delete()
132132
return Response({"status": "success", "message": "Quiz deleted"}, status=status.HTTP_200_OK)
133+
# --------------
133134

134135

135136
# - Quizzes and Questions:
136-
class QuizQuestionListView(APIView):
137+
class QQuestionListView(APIView):
137138
permission_classes = [IsAuthenticated]
138139

139140
# Fetch/get all questions for a quiz
@@ -272,4 +273,76 @@ def delete(self, request, assignment_id, quiz_id, question_id):
272273
return Response({"error": "Question not found"}, status=status.HTTP_404_NOT_FOUND)
273274

274275
Choice.delete_choices(question)
275-
return Response({"status": "success", "message": "All choices deleted"}, status=status.HTTP_200_OK)
276+
return Response({"status": "success", "message": "All choices deleted"}, status=status.HTTP_200_OK)
277+
# --------------
278+
279+
280+
# - Solutions:
281+
class SolutionDetailView(APIView):
282+
permission_classes = [IsAdminOrTutor]
283+
284+
# Helper method to check if object is found or not
285+
def get_object(self, question_id):
286+
try:
287+
# Assumes each question has one solution
288+
return Solution.objects.get(question__id=question_id)
289+
except Solution.DoesNotExist:
290+
return None
291+
292+
# Retrieve a solution for a given question (Admin/Tutor only)
293+
def get(self, request, question_id):
294+
solution = self.get_object(question_id)
295+
if not solution:
296+
return Response({"error": "Solution not found"}, status=status.HTTP_404_NOT_FOUND)
297+
serializer = SolutionSerializer(solution)
298+
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
299+
300+
301+
class SolutionCreateView(APIView):
302+
permission_classes = [IsAdminOrTutor]
303+
304+
# Create a Solution for a given question (Admin/Tutor only)
305+
def post(self, request, question_id):
306+
question = Question.get_question(question_id)
307+
if not question:
308+
return Response({"error": "Question not found"}, status=status.HTTP_404_NOT_FOUND)
309+
310+
data = request.data.copy()
311+
data["question"] = question_id # Associate the solution with the question
312+
313+
serializer = SolutionSerializer(data=data)
314+
if serializer.is_valid():
315+
serializer.save()
316+
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_201_CREATED)
317+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
318+
319+
320+
class SolutionUpdateView(APIView):
321+
permission_classes = [IsAdminOrTutor]
322+
323+
# Update the Solution for a given question (Admin/Tutor only)
324+
def put(self, request, question_id):
325+
try:
326+
solution = Solution.objects.get(question__id=question_id)
327+
except Solution.DoesNotExist:
328+
return Response({"error": "Solution not found"}, status=status.HTTP_404_NOT_FOUND)
329+
330+
serializer = SolutionSerializer(solution, data=request.data, partial=True)
331+
if serializer.is_valid():
332+
serializer.save()
333+
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
334+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
335+
336+
337+
class SolutionDeleteView(APIView):
338+
permission_classes = [IsAdminOrTutor]
339+
340+
# Delete the solution for a given question (Admin/Tutor only)
341+
def delete(self, request, question_id):
342+
try:
343+
solution = Solution.objects.get(question__id=question_id)
344+
except Solution.DoesNotExist:
345+
return Response({"error": "Solution not found"}, status=status.HTTP_404_NOT_FOUND)
346+
347+
solution.delete()
348+
return Response({"status": "success", "message": "Solution deleted"}, status=status.HTTP_200_OK)

0 commit comments

Comments
 (0)