All the views for our Quiz application.
Currently we support the following views:
Views are built with Generic Views from the Django REST framework.
from .models import *
from .serializers import *
Python Libraries
import json
import random
import hashlib
from django.shortcuts import get_object_or_404
from django.http import Http404
from django.db.models import Q
from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import ValidationError
import django_filters.rest_framework
from rest_framework import pagination
class UsersViewSet(generics.ListCreateAPIView):
serializer_class = UsersSerializer
querset = []
def get_queryset(self):
username = self.request.query_params.get('username', None)
if username is None:
queryset = Users.objects.all()
return queryset
def perform_create(self, serializer):
serializer.save()
class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
current = self.request.build_absolute_uri()
current_num = self.page.number
next_page = None
if self.page.has_next():
next_page = replace_query_param(
current, self.page_query_param, current_num+1)
previous = None
if current_num > 1:
previous = replace_query_param(
current, self.page_query_param, current_num-1)
return Response({
'next': next_page, # self.get_next_link(),
'previous': previous, # self.get_previous_link(),
'total_pages': int(self.page.paginator.count/int(self.page_size)),
'page_size': int(self.page_size),
'page': self.page.number,
'results': data,
})
The QuestionViewSet class defines the Questions endpoint that allows the user to get questions from the system and add questions to the system.
class QuestionViewSet(generics.ListCreateAPIView):
serializer_class = QuestionSerializer
queryset = []
Depending on the given parameters, this function returns a set of questions in the system either with pagination or without it.
The optional parameters are:
def get_queryset(self):
username = self.request.query_params.get('username', None)
if username is None:
queryset = Questions.objects.all()
queryset = Questions.objects.exclude(hidden=True)
return queryset
Add a Question
The function encrypts the prompt of a question to generate a unique ID for the question. If the question does not exist, the question will be added to the system. If it does, the question will not be added and the user will be prompted an error message.
def perform_create(self, serializer):
prompt = self.request.data.get('prompt', None)
id = hashlib.sha224(prompt.encode("utf-8")).hexdigest()
queryset = Questions.objects.filter(_id=id)
Checks if the a question with a same question id exists
if queryset.exists():
raise ValidationError('This question already exists.')
serializer.save(_id=id)
The QuestionModViewSet class defines the QuestionMod endpoint that allows the user to get, update and delete a specific question in the system.
class QuestionModViewSet(generics.RetrieveUpdateDestroyAPIView):
serializer_class = QuestionSerializer
lookup_field = '_id'
queryset = []
If required parameters are met, this function returns a specific question in the system.
The required parameters are:
def get_queryset(self):
id = self.kwargs['_id']
queryset = Questions.objects.filter(_id=id)
return queryset
If required parameters are met, this function updates a specific question in the system.
def perform_update(self, serializer):
serializer.save()
The QuestionRatingsViewSet class defines the MyQuestionRatings endpoint that allows the user to get and add ratings for a specific question in the system.
class QuestionRatingsViewSet(generics.ListCreateAPIView):
serializer_class = QuestionRatingsSerializer
If required parameters are met, this function returns a set of ratings associated with the question in the system.
The required parameters are:
def get(self, request, *args, **kwargs):
qid = self.request.query_params.get('qid', None)
queryset = QuestionRatings.objects.filter(qid=qid).values()
rating = 0
ratingCount = 0
for item in queryset:
rating += item['rating']
total = len(queryset)
if total == 0:
ratingDec = None
else:
ratingDec = rating/ratingCount
obj = {'qid': qid, 'rating': ratingDec,
'Number of ratings': ratingCount}
response = Response(obj)
return response
If required parameters are met, this function adds a rating associated with a question in the system.
def perform_create(self, serializer):
serializer.save()
class QuestionByIDViewSet(generics.ListCreateAPIView):
serializer_class = QuestionSerializer
def get_queryset(self):
id = self.request.query_params.get('qID', None)
queryset = Questions.objects.filter(_id=id)
return queryset
def post(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class QuestionIDByTopic(generics.ListCreateAPIView):
serializer_class = QuestionSerializer
def get_queryset(self):
topic = self.request.query_params.get('topic', None)
number = self.request.query_params.get('numQuestions', None)
queryset = Questions.objects.filter(
topic=topic, typename="multipleChoice")
if number is not None:
queryset = random.sample(list(queryset), int(number))
return queryset
class QuestionByLearningOutcome(generics.ListCreateAPIView):
serializer_class = QuestionLearningOutComeSerializer
def get_queryset(self):
topic = self.request.query_params.get('topic', None)
learningoutcome = self.request.query_params.get(
'learningoutcome', None)
learningoutcome = learningoutcome.split(",")
Gets the list of queries that need to be checked for learning outcome
queries = []
querysetquery = []
for item in learningoutcome:
queryset = QuestionLearningOutCome.objects.filter(
topic=topic, learningoutcome=item)
queryval = queryset.values()
queries.append(queryval)
querysetquery.append(queryset)
accepted = {}
counts to see if the question matches the number of times a learning outcome is shown
for item in queries:
for q in item:
if q['qid'] not in accepted:
accepted[q['qid']] = 1
else:
accepted[q['qid']] += 1
send = []
This is some nasty ass code maybe I’ll fix it later Anyway what it does its check to see if a question has a learningoutcome for each request one then it finds the index of the actual query item and adds it to a list
for item in accepted:
if accepted[item] == len(queries):
for i in range(len(queries)):
for j in range(len(queries[i])):
if item == queries[i][j]['qid']:
send.append(querysetquery[i][j])
return send
The ReviewQuizViewSet class defines the Quiz endpoint that allows the user to get and add quizzes in the system.
class ReviewQuizViewSet(generics.ListCreateAPIView):
serializer_class = ReviewQuizSerializer
If required parameters are met, this function returns a set of quizzes in the system.
The optional parameters are:
def get_queryset(self):
id = self.request.query_params.get("_id", None)
username = self.request.query_params.get("username", None)
if id is None and username is None:
queryset = ReviewQuiz.objects.all()
else:
if id is not None:
queryset = ReviewQuiz.objects.filter(_id=id)
if username is not None:
queryset = ReviewQuiz.objects.filter(username=username)
return queryset
If required parameters are met, this function adds a quiz to the system.
def perform_create(self, serializer):
serializer.save()
The TopicViewSet class defines the Topics endpoint that allows the user to get and add topics in the system.
class TopicViewSet(generics.ListCreateAPIView):
serializer_class = TopicsSerializer
queryset = []
If required parameters are met, this function returns a set of topics in the system.
The optional parameters are:
def get_queryset(self):
topic = self.request.query_params.get('name', None)
if topic is not None:
queryset = Topics.objects.filter(name=topic, hidden=False)
else:
queryset = Topics.objects.all().filter(hidden=False)
return queryset
If required parameters are met, this function add a topic to the system.
def perform_create(self, serializer):
serializer.save()
class TopicLearningOutcomeViewSet(generics.ListCreateAPIView):
serializer_class = TopicLearningOutcomeSerializer
def get_queryset(self):
topic = self.request.query_params.get('topic', None)
if topic is not None:
queryset = TopicLearningOutcome.objects.filter(topic=topic, hidden=False)
else:
queryset = TopicLearningOutcome.objects.all()
return queryset
def post(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
The TopicModViewSet class defines the TopicMod endpoint that allows the user to get, update and delete a specific topic in the system.
class TopicModViewSet(generics.RetrieveUpdateDestroyAPIView):
serializer_class = TopicsSerializer
lookup_field = 'name'
queryset = []
If required parameters are met, this function returns a specified topic in the system.
The required parameters are:
def get_queryset(self):
name = self.kwargs['name']
queryset = Topics.objects.filter(name=name, hidden=False)
return queryset
If required parameters are met, this function updates a specified topic in the system.
The required parameters are:
def perform_update(self, serializer):
instance = serializer.save()
The TopCommentViewSet class defines the Comment endpoint that allows the user to get and add comments for a question in the system.
class TopCommentViewSet(generics.ListCreateAPIView):
serializer_class = TopCommentSerializer
lookup_field = "_id"
If required parameters are met, this function returns a set of comments for a question in the system.
The optional parameters are:
def get_queryset(self):
questionId = self.request.query_params.get('questionID', None)
queryset = TopComment.objects.filter(parentid_id=questionId)
return queryset
If required parameters are met, this function add a comment for a question in the system.
def perform_create(self, serializer):
comment = self.request.data.get('comment', None)
topcommentid = hashlib.sha224(comment.encode("utf-8")).hexdigest()
parentid = self.request.data.get('parentid', None)
parentid = hashlib.sha224(parentid.encode("utf-8")).hexdigest()
finalid = topcommentid[:12] + parentid[12:]
queryset = TopComment.objects.filter(commentid=finalid)
if queryset.exists():
raise ValidationError('CommentID already Exists')
serializer.save(commentid=finalid)
class TopCommentUpdateViewSet(generics.UpdateAPIView):
serializer_class = TopCommentSerializer
def perform_update(self, serializer):
serializer.save()
class ChildCommentViewSet(generics.ListCreateAPIView):
serializer_class = ChildCommentSerializer
def get_queryset(self):
parentid = self.request.query_params.get('parentid', None)
queryset = ChildComment.objects.filter(parentid=parentid)
return queryset
def perform_create(self, serializer):
parentid = self.request.data.get('parentid', None)
parentid = hashlib.sha224(parentid.encode("utf-8")).hexdigest()
comment = self.request.data.get('comment', None)
id = hashlib.sha224(id.encode("utf-8")).hexdigest()
finalId = parentid[:12] + id[12:]
queryset = ChildComment.objects.filter(id=finalId)
if queryset.exists():
raise ValidationError('Comment already Exists')
serializer.save(id=finalId)
class ChildCommentUpdateViewSet(generics.UpdateAPIView):
serializer_class = ChildCommentSerializer
def perform_update(self, serializer):
serializer.save()
The StatisticsByTopicViewSet defines the endpoint that allows for the user to obtain statistics on quizzes for topics. It returns the topic and how many right/wrong answers there are. The GET can take two arguments: - userId: the id of the user you want statistics on (optional) - topicId: the topic you want statistics on (optional) If both are provided, it will return stats on a specific user for a specific topic, if no user is provided, but a topic is, it will return stats on all users for the given topic, if a topic is not given, but a user is, it will return the stats on all topics for that user, if neither is given, it will return all stats on all quizzes that have been taken.
class StatisticsByTopicViewSet(generics.ListCreateAPIView):
serializer_class = ReviewQuizSerializer
def get(self, request, *args, **kwargs):
topicId = self.request.query_params.get('topic', None)
userId = self.request.query_params.get('username', None)
Case 1: User and Topic provided
if userId != None and topicId != None:
queryset = ReviewQuiz.objects.filter(
topic=topicId, username=userId)
Case 2: Only Topic provided
elif topicId != None:
queryset = ReviewQuiz.objects.filter(topic=topicId)
Case 3: Only User provided
elif userId != None:
queryset = ReviewQuiz.objects.filter(username=userId)
Case 4: Nothing provided
else:
queryset = ReviewQuiz.objects.all()
retdict = {}
for item in queryset.values():
Add to dict
if item['topic_id'] not in retdict:
retdict[item['topic_id']] = {'topic': 0, 'correct': 0}
Increase count by total and correct for that quiz
retdict[item['topic_id']]['topic'] += item['total']
retdict[item['topic_id']]['correct'] += item['correct']
response = Response(retdict)
return response
The QuestionsForTopicAndLOCViewSet defines the endpoint that allows for the user to see how many questions exist for a given topic or learningoutcome There are two arguments that may be passed to this function: - topic: the topic you want information on (optional) - learningOutcome: the learning Outcome you want information on (optional) If only a topic is provided, it will return stats on that topic, if a learningoutcome is also specified, it will return informatin on the topic and only that learning outcome if neither is specified, it will return info on all topics.
class QuestionsForTopicAndLOCViewSet(generics.ListCreateAPIView):
serializer_class = QuestionSerializer
def get(self, request, *args, **kwargs):
topic = self.request.query_params.get('topic', None)
learningOutcome = self.request.query_params.get(
'learningOutcome', None)
if topic != None:
querysetTopic = Questions.objects.filter(topic=topic).values()
else:
querysetTopic = Questions.objects.all().values()
retdict = {}
If a topic was given, get size, else find total topics
if topic != None:
retdict[topic] = {'total': len(querysetTopic)}
Gets LOC if provided
if learningOutcome != None:
for item in querysetTopic:
if learningOutcome in item['learningoutcome']:
if learningOutcome not in retdict[item['topic_id']]:
retdict[item['topic_id']][learningOutcome] = 1
else:
retdict[item['topic_id']][learningOutcome] += 1
else:
for item in querysetTopic:
for val in item['learningoutcome']:
if val not in retdict[item['topic_id']]:
retdict[item['topic_id']][val] = 1
else:
retdict[item['topic_id']][val] += 1
else:
for item in querysetTopic:
Get number of questions
if item['topic_id'] not in retdict:
retdict[item['topic_id']] = {'Total': 1}
else:
retdict[item['topic_id']]['Total'] += 1
Gets LOC if provided
for val in item['learningoutcome']:
if val not in retdict[item['topic_id']]:
retdict[item['topic_id']][val] = 1
else:
retdict[item['topic_id']][val] += 1
response = Response(retdict)
return response
The UserMadeQuestionRatingsViewSet defines the endpoint that allows a user to see the ratings of their questions it takes two parameters: - username: the username of the person you want statistics on (optional) - qid: the question id you want information on (optional) if you want to see how all questions are rated for a user, you can provide their username, if you want to specifically see one question, you can provide the question id.
Note that at least one of them MUST be provided
class UserMadeQuestionRatingsViewSet(generics.ListCreateAPIView):
serializer_class = QuestionRatingsSerializer
def get(self, request, *args, **kwargs):
username = self.request.query_params.get('username', None)
qid = self.request.query_params.get('qid', None)
queryset = None
qid for specific user for generic all my qs
if qid != None:
queryset = QuestionRatings.objects.filter(qid=qid).values()
if username != None:
questions = Questions.objects.filter(username=username).values()
queryset = []
for item in questions:
items = QuestionRatings.objects.filter(
qid=item['_id']).values()
for val in items:
queryset.append(val)
if queryset == None:
return Response("Error: you need to provide a qid or username")
obj = {}
count = {}
for item in queryset:
if item['qid_id'] not in obj:
obj[item['qid_id']] = item['rating']
count[item['qid_id']] = 1
else:
obj[item['qid_id']] += item['rating']
count[item['qid_id']] += 1
for item in obj:
obj[item] = obj[item]/count[item]
response = Response(obj)
return response
If required parameters are met, this function adds a rating to the system.
def perform_create(self, serializer):
serializer.save()