diff --git a/api/tests.py b/api/tests.py index 03de6662d..e2a8346c6 100644 --- a/api/tests.py +++ b/api/tests.py @@ -32,14 +32,18 @@ def setUp(self): self.password = 'demo' self.user = User.objects.create_user(username=self.username, password=self.password) + self.otheruser = User.objects.create_user(username='other', + password=self.password) Question.objects.create(summary='test question 1', language='python', type='mcq', user=self.user) Question.objects.create(summary='test question 2', language='python', type='mcq', user=self.user) + Question.objects.create(summary='test question 3', language='python', + type='mcq', user=self.otheruser) def test_get_all_questions_anonymous(self): # When - response = self.client.get(reverse('api:questions')) + response = self.client.get(reverse('api:question-list')) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -49,7 +53,7 @@ def test_get_all_questions(self): serializer = QuestionSerializer(questions, many=True) # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:questions')) + response = self.client.get(reverse('api:question-list')) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 2) @@ -60,7 +64,7 @@ def test_create_question_invalid_data(self): data = {'summary': 'Add test question', 'user': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.post(reverse('api:questions'), data) + response = self.client.post(reverse('api:question-list'), data) # Then self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertFalse(Question.objects.filter( @@ -72,11 +76,13 @@ def test_create_question_valid_data(self): 'language': 'python', 'type': 'mcq', 'user': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.post(reverse('api:questions'), data) + response = self.client.post(reverse('api:question-list'), data) # Then self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(Question.objects.filter( summary='Add test question').exists()) + question = Question.objects.get(summary='Add test question') + self.assertTrue(self.user, question.user) def tearDown(self): self.client.logout() @@ -108,7 +114,7 @@ def test_get_question_anonymous(self): # Given question = Question.objects.get(summary='test question') # When - response = self.client.get(reverse('api:question', + response = self.client.get(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -118,7 +124,7 @@ def test_get_question_invalid_pk(self): invalid_pk = 3243 # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:question', + response = self.client.get(reverse('api:question-detail', kwargs={'pk': invalid_pk})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -129,7 +135,7 @@ def test_get_question(self): serializer = QuestionSerializer(question) # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:question', + response = self.client.get(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -140,7 +146,7 @@ def test_get_question_not_own(self): question = Question.objects.get(summary='Created by other user') # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:question', + response = self.client.get(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -151,7 +157,7 @@ def test_edit_question_anonymous(self): data = {'summary': 'Edited test question', 'description': 'test', 'language': 'python', 'type': 'mcq', 'user': self.user.id} # When - response = self.client.put(reverse('api:question', + response = self.client.put(reverse('api:question-detail', kwargs={'pk': question.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -162,7 +168,7 @@ def test_edit_question_invalid_data(self): data = {'summary': 'Edited test question', 'user': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.put(reverse('api:question', + response = self.client.put(reverse('api:question-detail', kwargs={'pk': question.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -174,7 +180,7 @@ def test_edit_question(self): 'language': 'python', 'type': 'mcq', 'user': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.put(reverse('api:question', + response = self.client.put(reverse('api:question-detail', kwargs={'pk': question.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -185,7 +191,7 @@ def test_delete_question_anonymous(self): # Given question = Question.objects.get(summary='delete question') # When - response = self.client.delete(reverse('api:question', + response = self.client.delete(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -195,7 +201,7 @@ def test_delete_question_not_own(self): question = Question.objects.get(summary='Created by other user') # When self.client.login(username=self.username, password=self.password) - response = self.client.delete(reverse('api:question', + response = self.client.delete(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -206,7 +212,7 @@ def test_delete_question(self): question = Question.objects.get(summary='delete question') # When self.client.login(username=self.username, password=self.password) - response = self.client.delete(reverse('api:question', + response = self.client.delete(reverse('api:question-detail', kwargs={'pk': question.id})) # Then self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -307,6 +313,7 @@ def test_create_questionpaper_valid_data(self): # Then self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(QuestionPaper.objects.filter(quiz=self.quiz4).exists()) + qp = QuestionPaper.objects.get(quiz=self.quiz4) def test_create_questionpaper_not_own_quiz(self): # Given @@ -391,6 +398,19 @@ def test_edit_questionpaper(self): questionpaper = QuestionPaper.objects.get(pk=questionpaper.id) self.assertEqual(questionpaper.quiz.id, self.quiz5.id) + def test_edit_questionpaper_not_own(self): + # Given + questionpaper = self.questionpaper2 + data = {'quiz': self.quiz5.id, + 'fixed_questions': [self.question1.id, self.question2.id], + 'random_questions': [self.questionset.id]} + # When + self.client.login(username=self.otherusername, password=self.password) + response = self.client.put(reverse('api:questionpaper', + kwargs={'pk': questionpaper.id}), data) + # Then + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + def test_delete_questionpaper(self): # Given questionpaper = self.questionpaper2 @@ -420,12 +440,15 @@ def setUp(self): self.password = 'demo' self.user = User.objects.create_user(username=self.username, password=self.password) + self.other = User.objects.create_user(username='other', + password=self.password) Quiz.objects.create(description='Test Quiz 1', creator=self.user) Quiz.objects.create(description='Test Quiz 2', creator=self.user) + Quiz.objects.create(description='Test Quiz 2', creator=self.other) def test_get_all_quizzes_anonymous(self): # When - response = self.client.get(reverse('api:quizzes')) + response = self.client.get(reverse('api:quiz-list')) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -435,7 +458,7 @@ def test_get_all_quizzes(self): serializer = QuizSerializer(quizzes, many=True) # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:quizzes')) + response = self.client.get(reverse('api:quiz-list')) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 2) @@ -446,7 +469,7 @@ def test_create_quiz_invalid_data(self): data = {'creator': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.post(reverse('api:quizzes'), data) + response = self.client.post(reverse('api:quiz-list'), data) # Then self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -455,7 +478,7 @@ def test_create_quiz_valid_data(self): data = {'description': 'Added quiz', 'creator': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.post(reverse('api:quizzes'), data) + response = self.client.post(reverse('api:quiz-list'), data) # Then self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(Quiz.objects.filter(description='Added quiz').exists()) @@ -487,7 +510,8 @@ def test_get_quiz_anonymous(self): # Given quiz = Quiz.objects.get(description='Quiz1') # When - response = self.client.get(reverse('api:quiz', kwargs={'pk': quiz.id})) + response = self.client.get(reverse('api:quiz-detail', + kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -496,7 +520,7 @@ def test_get_quiz_invalid_pk(self): invalid_pk = 3242 # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:quiz', + response = self.client.get(reverse('api:quiz-detail', kwargs={'pk': invalid_pk})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -507,7 +531,7 @@ def test_get_quiz(self): serializer = QuizSerializer(quiz) # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:quiz', + response = self.client.get(reverse('api:quiz-detail', kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -518,7 +542,8 @@ def test_get_quiz_not_own(self): quiz = Quiz.objects.get(description='Quiz3') # When self.client.login(username=self.username, password=self.password) - response = self.client.get(reverse('api:quiz', kwargs={'pk': quiz.id})) + response = self.client.get(reverse('api:quiz-detail', + kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -527,8 +552,8 @@ def test_edit_quiz_anonymous(self): quiz = Quiz.objects.get(description='Quiz1') data = {'description': 'Quiz1 Edited', 'creator': self.user.id} # When - response = self.client.put(reverse('api:quiz', kwargs={'pk': quiz.id}), - data) + response = self.client.put(reverse('api:quiz-detail', + kwargs={'pk': quiz.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -538,8 +563,8 @@ def test_edit_quiz_invalid_data(self): data = {'creator': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.put(reverse('api:quiz', kwargs={'pk': quiz.id}), - data) + response = self.client.put(reverse('api:quiz-detail', + kwargs={'pk': quiz.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -549,8 +574,8 @@ def test_edit_quiz(self): data = {'description': 'Quiz2 edited', 'creator': self.user.id} # When self.client.login(username=self.username, password=self.password) - response = self.client.put(reverse('api:quiz', kwargs={'pk': quiz.id}), - data) + response = self.client.put(reverse('api:quiz-detail', + kwargs={'pk': quiz.id}), data) # Then self.assertEqual(response.status_code, status.HTTP_200_OK) quiz = Quiz.objects.get(pk=quiz.id) @@ -560,7 +585,7 @@ def test_delete_quiz_anonymous(self): # Given quiz = Quiz.objects.get(description='delete quiz') # When - response = self.client.delete(reverse('api:quiz', + response = self.client.delete(reverse('api:quiz-detail', kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) @@ -570,7 +595,7 @@ def test_delete_quiz_not_own(self): quiz = Quiz.objects.get(description='Quiz3') # When self.client.login(username=self.username, password=self.password) - response = self.client.delete(reverse('api:quiz', + response = self.client.delete(reverse('api:quiz-detail', kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -581,7 +606,7 @@ def test_delete_quiz(self): quiz = Quiz.objects.get(description='delete quiz') # When self.client.login(username=self.username, password=self.password) - response = self.client.delete(reverse('api:quiz', + response = self.client.delete(reverse('api:quiz-detail', kwargs={'pk': quiz.id})) # Then self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) diff --git a/api/urls.py b/api/urls.py index f519aea0f..761bad120 100644 --- a/api/urls.py +++ b/api/urls.py @@ -2,21 +2,21 @@ from rest_framework.urlpatterns import format_suffix_patterns from api import views +from rest_framework.routers import SimpleRouter +from django.urls import path, include + app_name = 'api' +router = SimpleRouter() +router.register(r'questions', views.QuestionViewSet, basename='question') +router.register(r'quizzes', views.QuizViewSet, basename='quiz') + + urlpatterns = [ - url(r'questions/$', views.QuestionList.as_view(), name='questions'), - url(r'questions/(?P[0-9]+)/$', views.QuestionDetail.as_view(), - name='question'), + path('', include(router.urls)), url(r'get_courses/$', views.CourseList.as_view(), name='get_courses'), url(r'start_quiz/(?P[0-9]+)/(?P[0-9]+)/$', views.StartQuiz.as_view(), name='start_quiz'), - url(r'quizzes/$', views.QuizList.as_view(), name='quizzes'), - url(r'quizzes/(?P[0-9]+)/$', views.QuizDetail.as_view(), name='quiz'), - url(r'questionpapers/$', views.QuestionPaperList.as_view(), - name='questionpapers'), - url(r'questionpapers/(?P[0-9]+)/$', - views.QuestionPaperDetail.as_view(), name='questionpaper'), url(r'answerpapers/$', views.AnswerPaperList.as_view(), name='answerpapers'), url(r'validate/(?P[0-9]+)/(?P[0-9]+)/$', @@ -27,7 +27,11 @@ views.GetCourse.as_view(), name='get_course'), url(r'quit/(?P\d+)/$', views.QuitQuiz.as_view(), name="quit_quiz"), - url(r'login/$', views.login, name='login') + url(r'login/$', views.login, name='login'), + url(r'questionpapers/$', views.QuestionPaperList.as_view(), + name='questionpapers'), + url(r'questionpapers/(?P[0-9]+)/$', + views.QuestionPaperDetail.as_view(), name='questionpaper'), ] urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/api/views.py b/api/views.py index 8d2da8318..17555c046 100644 --- a/api/views.py +++ b/api/views.py @@ -19,22 +19,27 @@ from yaksh.settings import SERVER_POOL_PORT, SERVER_HOST_NAME import json +from rest_framework import viewsets -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) +class QuestionViewSet(viewsets.ModelViewSet): + serializer_class = QuestionSerializer + + def get_queryset(self): + return Question.objects.filter(user=self.request.user) - 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 QuizViewSet(viewsets.ModelViewSet): + serializer_class = QuizSerializer + + def get_queryset(self): + return Quiz.objects.filter(creator=self.request.user) + +class GetCourse(APIView): + def get(self, request, pk, format=None): + course = Course.objects.get(id=pk) + serializer = CourseSerializer(course) + return Response(serializer.data) class CourseList(APIView): """ List all courses """ @@ -84,34 +89,6 @@ def get(self, request, course_id, quiz_id, format=None): 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): @@ -236,57 +213,12 @@ def get(self, request, uid): 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() @@ -311,7 +243,7 @@ def check_questionsets_creator(self, user, questionset_ids): 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) @@ -393,13 +325,6 @@ def delete(self, request, pk, format=None): 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(()) @@ -429,4 +354,4 @@ def get(self, request, answerpaper_id, format=None): answerpaper.status = 'completed' answerpaper.save() serializer = AnswerPaperSerializer(answerpaper) - return Response(serializer.data) \ No newline at end of file + return Response(serializer.data)