summaryrefslogtreecommitdiff
path: root/api/views.py
diff options
context:
space:
mode:
authorPalaparthy Adityachandra2020-04-30 17:39:44 +0530
committerGitHub2020-04-30 17:39:44 +0530
commit833b96ac49499810934ada8ba02750623455d0cd (patch)
tree16d974b5a5e1effaf15be2235813dca4108c4f29 /api/views.py
parent53a0c4ad3e733f3960000527f83565f2fd8fc412 (diff)
parent2fd29bf1fff3d57a49b8a5cdffa9efc305946214 (diff)
downloadonline_test-833b96ac49499810934ada8ba02750623455d0cd.tar.gz
online_test-833b96ac49499810934ada8ba02750623455d0cd.tar.bz2
online_test-833b96ac49499810934ada8ba02750623455d0cd.zip
Merge pull request #674 from CruiseDevice/API
Update Yaksh API
Diffstat (limited to 'api/views.py')
-rw-r--r--api/views.py432
1 files changed, 432 insertions, 0 deletions
diff --git a/api/views.py b/api/views.py
new file mode 100644
index 0000000..8d2da83
--- /dev/null
+++ b/api/views.py
@@ -0,0 +1,432 @@
+from yaksh.models import (
+ Question, Quiz, QuestionPaper, QuestionSet, AnswerPaper, Course, Answer
+)
+from api.serializers import (
+ QuestionSerializer, QuizSerializer, QuestionPaperSerializer,
+ AnswerPaperSerializer, CourseSerializer
+)
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework import status
+from rest_framework import permissions
+from rest_framework.authtoken.models import Token
+from rest_framework.decorators import (
+ api_view, authentication_classes, permission_classes
+)
+from django.http import Http404
+from django.contrib.auth import authenticate
+from yaksh.code_server import get_result as get_result_from_code_server
+from yaksh.settings import SERVER_POOL_PORT, SERVER_HOST_NAME
+import json
+
+
+class QuestionList(APIView):
+ """ List all questions or create a new question. """
+
+ def get(self, request, format=None):
+ questions = Question.objects.filter(user=request.user)
+ serializer = QuestionSerializer(questions, many=True)
+ return Response(serializer.data)
+
+ def post(self, request, format=None):
+ serializer = QuestionSerializer(data=request.data)
+ if serializer.is_valid():
+ serializer.save()
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+
+class CourseList(APIView):
+ """ List all courses """
+
+ def get(self, request, format=None):
+ courses = Course.objects.filter(students=request.user)
+ serializer = CourseSerializer(courses, many=True)
+ return Response(serializer.data)
+
+
+class StartQuiz(APIView):
+ """ Retrieve Answerpaper. If does not exists then create one """
+
+ def get_quiz(self, pk, user):
+ try:
+ return Quiz.objects.get(pk=pk)
+ except Quiz.DoesNotExist:
+ raise Http404
+
+ def get(self, request, course_id, quiz_id, format=None):
+ context = {}
+ user = request.user
+ quiz = self.get_quiz(quiz_id, user)
+ questionpaper = quiz.questionpaper_set.first()
+
+ last_attempt = AnswerPaper.objects.get_user_last_attempt(
+ questionpaper, user, course_id)
+ if last_attempt and last_attempt.is_attempt_inprogress():
+ serializer = AnswerPaperSerializer(last_attempt)
+ context["time_left"] = last_attempt.time_left()
+ context["answerpaper"] = serializer.data
+ return Response(context)
+
+ can_attempt, msg = questionpaper.can_attempt_now(user, course_id)
+ if not can_attempt:
+ return Response({'message': msg})
+ if not last_attempt:
+ attempt_number = 1
+ else:
+ attempt_number = last_attempt.attempt_number + 1
+ ip = request.META['REMOTE_ADDR']
+ answerpaper = questionpaper.make_answerpaper(user, ip, attempt_number,
+ course_id)
+ serializer = AnswerPaperSerializer(answerpaper)
+ context["time_left"] = answerpaper.time_left()
+ context["answerpaper"] = serializer.data
+ return Response(context, status=status.HTTP_201_CREATED)
+
+
+class QuestionDetail(APIView):
+ """ Retrieve, update or delete a question """
+
+ def get_question(self, pk, user):
+ try:
+ return Question.objects.get(pk=pk, user=user)
+ except Question.DoesNotExist:
+ raise Http404
+
+ def get(self, request, pk, format=None):
+ question = self.get_question(pk, request.user)
+ serializer = QuestionSerializer(question)
+ return Response(serializer.data)
+
+ def put(self, request, pk, format=None):
+ question = self.get_question(pk, request.user)
+ serializer = QuestionSerializer(question, data=request.data)
+ if serializer.is_valid():
+ serializer.save()
+ return Response(serializer.data)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+ def delete(self, request, pk, format=None):
+ question = self.get_question(pk, request.user)
+ question.delete()
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
+
+class AnswerPaperList(APIView):
+
+ def get_questionpaper(self, pk):
+ try:
+ return QuestionPaper.objects.get(pk=pk)
+ except QuestionPaper.DoesNotExist:
+ raise Http404
+
+ def get_course(self, pk):
+ try:
+ return Course.objects.get(pk=pk)
+ except Course.DoesNotExist:
+ raise Http404
+
+ def get_answerpapers(self, user):
+ return AnswerPaper.objects.filter(question_paper__quiz__creator=user)
+
+ def get(self, request, format=None):
+ user = request.user
+ answerpapers = self.get_answerpapers(user)
+ serializer = AnswerPaperSerializer(answerpapers, many=True)
+ return Response(serializer.data)
+
+ def is_user_allowed(self, user, course):
+ ''' if user is student or teacher or creator then allow '''
+ return user in course.students.all() or user in course.teachers.all() \
+ or user == course.creator
+
+ def post(self, request, format=None):
+ try:
+ questionpaperid = request.data['question_paper']
+ attempt_number = request.data['attempt_number']
+ course_id = request.data['course']
+ except KeyError:
+ return Response(status=status.HTTP_400_BAD_REQUEST)
+ user = request.user
+ ip = request.META['REMOTE_ADDR']
+ questionpaper = self.get_questionpaper(questionpaperid)
+ course = self.get_course(course_id)
+ if not self.is_user_allowed(user, course):
+ return Response(status=status.HTTP_400_BAD_REQUEST)
+ answerpaper = questionpaper.make_answerpaper(user, ip, attempt_number,
+ course_id)
+ serializer = AnswerPaperSerializer(answerpaper)
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+
+
+class AnswerValidator(APIView):
+
+ def get_answerpaper(self, pk, user):
+ try:
+ return AnswerPaper.objects.get(pk=pk, user=user)
+ except AnswerPaper.DoesNotExist:
+ raise Http404
+
+ def get_question(self, pk, answerpaper):
+ try:
+ question = Question.objects.get(pk=pk)
+ if question in answerpaper.questions.all():
+ return question
+ else:
+ raise Http404
+ except AnswerPaper.DoesNotExist:
+ raise Http404
+
+ def get_answer(self, pk):
+ try:
+ return Answer.objects.get(pk=pk)
+ except Answer.DoesNotExist:
+ raise Http404
+
+ def post(self, request, answerpaper_id, question_id, format=None):
+ user = request.user
+ answerpaper = self.get_answerpaper(answerpaper_id, user)
+ question = self.get_question(question_id, answerpaper)
+ try:
+ if question.type == 'mcq' or question.type == 'mcc':
+ user_answer = request.data['answer']
+ elif question.type == 'integer':
+ user_answer = int(request.data['answer'][0])
+ elif question.type == 'float':
+ user_answer = float(request.data['answer'][0])
+ elif question.type == 'string':
+ user_answer = request.data['answer']
+ else:
+ user_answer = request.data['answer']
+ except KeyError:
+ return Response(status=status.HTTP_400_BAD_REQUEST)
+ # save answer uid
+ answer = Answer.objects.create(question=question, answer=user_answer)
+ answerpaper.answers.add(answer)
+ answerpaper.save()
+ json_data = None
+ if question.type in ['code', 'upload']:
+ json_data = question.consolidate_answer_data(user_answer, user)
+ result = answerpaper.validate_answer(user_answer, question, json_data,
+ answer.id)
+
+ # updaTE RESult
+ if question.type not in ['code', 'upload']:
+ if result.get('success'):
+ answer.correct = True
+ answer.marks = question.points
+ answer.error = json.dumps(result.get('error'))
+ answer.save()
+ answerpaper.update_marks(state='inprogress')
+ return Response(result)
+
+ def get(self, request, uid):
+ answer = self.get_answer(uid)
+ url = '{0}:{1}'.format(SERVER_HOST_NAME, SERVER_POOL_PORT)
+ result = get_result_from_code_server(url, uid)
+ # update result
+ if result['status'] == 'done':
+ final_result = json.loads(result.get('result'))
+ answer.error = json.dumps(final_result.get('error'))
+ if final_result.get('success'):
+ answer.correct = True
+ answer.marks = answer.question.points
+ answer.save()
+ answerpaper = answer.answerpaper_set.get()
+ answerpaper.update_marks(state='inprogress')
+ return Response(result)
+
+
+class QuizList(APIView):
+ """ List all quizzes or create a new quiz """
+
+ def get(self, request, format=None):
+ quizzes = Quiz.objects.filter(creator=request.user)
+ serializer = QuizSerializer(quizzes, many=True)
+ return Response(serializer.data)
+
+ def post(self, request, format=None):
+ serializer = QuizSerializer(data=request.data)
+ if serializer.is_valid():
+ serializer.save()
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+
+class QuizDetail(APIView):
+ """ Retrieve, update or delete a quiz """
+
+ def get_quiz(self, pk, user):
+ try:
+ return Quiz.objects.get(pk=pk, creator=user)
+ except Quiz.DoesNotExist:
+ raise Http404
+
+ def get(self, request, pk, format=None):
+ quiz = self.get_quiz(pk, request.user)
+ serializer = QuizSerializer(quiz)
+ return Response(serializer.data)
+
+ def put(self, request, pk, format=None):
+ quiz = self.get_quiz(pk, request.user)
+ serializer = QuizSerializer(quiz, data=request.data)
+ if serializer.is_valid():
+ serializer.save()
+ return Response(serializer.data)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+ def delete(self, request, pk, format=None):
+ quiz = self.get_quiz(pk, request.user)
+ quiz.delete()
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
+
+class QuestionPaperList(APIView):
+ """ List all question papers or create a new question paper """
+
+ def get_questionpapers(self, user):
+ return QuestionPaper.objects.filter(quiz__creator=user)
+
+ def questionpaper_exists(self, quiz_id):
+ return QuestionPaper.objects.filter(quiz=quiz_id).exists()
+
+ def check_quiz_creator(self, user, quiz_id):
+ try:
+ Quiz.objects.get(pk=quiz_id, creator=user)
+ except Quiz.DoesNotExist:
+ raise Http404
+
+ def check_questions_creator(self, user, question_ids):
+ for question_id in question_ids:
+ try:
+ Question.objects.get(pk=question_id, user=user)
+ except Question.DoesNotExist:
+ raise Http404
+
+ def check_questionsets_creator(self, user, questionset_ids):
+ for question_id in questionset_ids:
+ try:
+ questionset = QuestionSet.objects.get(pk=question_id)
+ for question in questionset.questions.all():
+ Question.objects.get(pk=question.id, user=user)
+ except (QuestionSet.DoesNotExist, Question.DoesNotExist):
+ raise Http404
+
+ def get(self, request, format=None):
+ questionpapers = self.get_questionpapers(request.user)
+ serializer = QuestionPaperSerializer(questionpapers, many=True)
+ return Response(serializer.data)
+
+ def post(self, request, format=None):
+ serializer = QuestionPaperSerializer(data=request.data)
+ if serializer.is_valid():
+ user = request.user
+ quiz_id = request.data.get('quiz')
+ question_ids = request.data.get('fixed_questions', [])
+ questionset_ids = request.data.get('random_questions', [])
+ if self.questionpaper_exists(quiz_id):
+ return Response({'error': 'Already exists'},
+ status=status.HTTP_409_CONFLICT)
+ self.check_quiz_creator(user, quiz_id)
+ self.check_questions_creator(user, question_ids)
+ self.check_questionsets_creator(user, questionset_ids)
+ serializer.save()
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
+
+
+class QuestionPaperDetail(APIView):
+ """ Retrieve, update or delete a question paper"""
+
+ def get_questionpaper(self, pk, user):
+ try:
+ return QuestionPaper.objects.get(pk=pk, quiz__creator=user)
+ except QuestionPaper.DoesNotExist:
+ raise Http404
+
+ def get(self, request, pk, format=None):
+ questionpaper = self.get_questionpaper(pk, request.user)
+ serializer = QuestionPaperSerializer(questionpaper)
+ return Response(serializer.data)
+
+ def check_quiz_creator(self, user, quiz_id):
+ try:
+ Quiz.objects.get(pk=quiz_id, creator=user)
+ except Quiz.DoesNotExist:
+ raise Http404
+
+ def check_questions_creator(self, user, question_ids):
+ for question_id in question_ids:
+ try:
+ Question.objects.get(pk=question_id, user=user)
+ except Question.DoesNotExist:
+ raise Http404
+
+ def check_questionsets_creator(self, user, questionset_ids):
+ for question_id in questionset_ids:
+ try:
+ questionset = QuestionSet.objects.get(pk=question_id)
+ for question in questionset.questions.all():
+ Question.objects.get(pk=question.id, user=user)
+ except (QuestionSet.DoesNotExist, Question.DoesNotExist):
+ raise Http404
+
+ def put(self, request, pk, format=None):
+ user = request.user
+ questionpaper = self.get_questionpaper(pk, user)
+ serializer = QuestionPaperSerializer(questionpaper, data=request.data)
+ if serializer.is_valid():
+ user = request.user
+ quiz_id = request.data.get('quiz')
+ question_ids = request.data.get('fixed_questions', [])
+ questionset_ids = request.data.get('random_questions', [])
+ self.check_quiz_creator(user, quiz_id)
+ self.check_questions_creator(user, question_ids)
+ self.check_questionsets_creator(user, questionset_ids)
+ serializer.save()
+ return Response(serializer.data)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+ def delete(self, request, pk, format=None):
+ questionpaper = self.get_questionpaper(pk, request.user)
+ questionpaper.delete()
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
+
+class GetCourse(APIView):
+ def get(self, request, pk, format=None):
+ course = Course.objects.get(id=pk)
+ serializer = CourseSerializer(course)
+ return Response(serializer.data)
+
+
+@api_view(['POST'])
+@authentication_classes(())
+@permission_classes(())
+def login(request):
+ data = {}
+ if request.method == "POST":
+ username = request.data.get('username')
+ password = request.data.get('password')
+ user = authenticate(username=username, password=password)
+ if user is not None and user.is_authenticated:
+ token, created = Token.objects.get_or_create(user=user)
+ data = {
+ 'token': token.key
+ }
+ return Response(data, status=status.HTTP_201_CREATED)
+
+
+class QuitQuiz(APIView):
+ def get_answerpaper(self, answerpaper_id):
+ try:
+ return AnswerPaper.objects.get(id=answerpaper_id)
+ except AnswerPaper.DoesNotExist:
+ raise Http404
+
+ def get(self, request, answerpaper_id, format=None):
+ answerpaper = self.get_answerpaper(answerpaper_id)
+ answerpaper.status = 'completed'
+ answerpaper.save()
+ serializer = AnswerPaperSerializer(answerpaper)
+ return Response(serializer.data) \ No newline at end of file