Commit a7e5bbea by Afzal Wali

Create Exam API

parent e577b8a6
......@@ -21,16 +21,16 @@ class ProctoredExam(TimeStampedModel):
# This will be a integration specific ID - say to SoftwareSecure.
external_id = models.TextField(null=True, db_index=True)
# This is the display name of the course
# This is the display name of the Exam (Midterm etc).
exam_name = models.TextField()
# Time limit (in minutes) that a student can finish this exam
# Time limit (in minutes) that a student can finish this exam.
time_limit_mins = models.IntegerField()
# Whether this exam actually is proctored or not
# Whether this exam actually is proctored or not.
is_proctored = models.BooleanField()
# This will be a integration specific ID - say to SoftwareSecure.
# Whether this exam will be active.
is_active = models.BooleanField()
class Meta:
......@@ -65,7 +65,7 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
class QuerySetWithUpdateOverride(models.query.QuerySet):
"""
Custom QuerySet class to send the POST_UPDATE_SIGNAL
Custom QuerySet class to make an archive copy
every time the object is updated.
"""
def update(self, **kwargs):
......@@ -76,7 +76,7 @@ class QuerySetWithUpdateOverride(models.query.QuerySet):
class ProctoredExamStudentAllowanceManager(models.Manager):
"""
Custom manager to override with the custom queryset
to enable the POST_UPDATE_SIGNAL
to enable archiving on Allowance updation.
"""
def get_query_set(self):
return QuerySetWithUpdateOverride(self.model, using=self._db)
......@@ -120,7 +120,7 @@ class ProctoredExamStudentAllowanceHistory(TimeStampedModel):
value = models.CharField(max_length=255)
# Hook up the custom POST_UPDATE_SIGNAL signal to record updations in the ProctoredExamStudentAllowanceHistory table.
# Hook up the post_save signal to record creations in the ProctoredExamStudentAllowanceHistory table.
@receiver(post_save, sender=ProctoredExamStudentAllowance)
def on_allowance_saved(sender, instance, created, **kwargs): # pylint: disable=unused-argument
"""
......
......@@ -12,5 +12,10 @@ urlpatterns = patterns( # pylint: disable=invalid-name
views.StudentProctoredExamStatus.as_view(),
name='edx_proctoring.proctored_exam.status'
),
url(
r'edx_proctoring/v1/proctored_exam/create$',
views.CreateExamView.as_view(),
name='edx_proctoring.proctored_exam.create'
),
url(r'^', include('rest_framework.urls', namespace='rest_framework'))
)
......@@ -3,9 +3,11 @@ Proctored Exams HTTP-based API endpoints
"""
import logging
from django.db import IntegrityError
from rest_framework import status
from rest_framework.response import Response
from edx_proctoring.api import create_exam
from .utils import AuthenticatedAPIView
......@@ -33,3 +35,59 @@ class StudentProctoredExamStatus(AuthenticatedAPIView):
}
return Response(response_dict, status=status.HTTP_200_OK)
class CreateExamView(AuthenticatedAPIView):
"""
Creates a new Exam.
POST /edx_proctoring/v1/proctored_exam/create
{
"course_id": "edX/DemoX/Demo_Course",
"content_id": "",
"exam_name": "Midterm",
"time_limit_mins": "90",
"is_proctored": true,
"external_id": "",
"is_active": true,
}
**Post Parameters**
* course_id: The unique identifier for the course.
* content_id: This will be the pointer to the id of the piece of course_ware which is the proctored exam.
* exam_name: This is the display name of the Exam (Midterm etc).
* time_limit_mins: Time limit (in minutes) that a student can finish this exam.
* is_proctored: Whether this exam actually is proctored or not.
* external_id: This will be a integration specific ID - say to SoftwareSecure.
* is_active: Whether this exam will be active.
**Response Values**
* {'exam_id': ##}, The exam_id of the created Proctored Exam.
**Exceptions**
* HTTP_400_BAD_REQUEST, data={"message": "Trying to create a duplicate exam."}
"""
def post(self, request):
"""
Http POST handler.
"""
try:
exam_id = create_exam(
course_id=request.DATA.get('course_id', ""),
content_id=request.DATA.get('content_id', ""),
exam_name=request.DATA.get('exam_name', ""),
time_limit_mins=request.DATA.get('time_limit_mins', ""),
is_proctored=True if request.DATA.get('is_proctored', "False").lower()=='true' else False,
external_id=request.DATA.get('external_id', ""),
is_active=True if request.DATA.get('is_active', "").lower()=='true' else False,
)
return Response({'exam_id': exam_id})
except IntegrityError:
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={"message": u"Trying to create a duplicate exam."}
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment