summaryrefslogtreecommitdiff
path: root/testapp/exam/views.py
diff options
context:
space:
mode:
authorPrabhu Ramachandran2015-05-12 20:20:43 +0530
committerPrabhu Ramachandran2015-05-12 20:20:43 +0530
commita022e0145ec8fb1622d58c2e2281c016b1d45b01 (patch)
tree1c0c3f2e8605d6f36405c57cbe5de9a895a47958 /testapp/exam/views.py
parentcd9f2542d09db0e4a352dd410f626f27e23c37e4 (diff)
parent5b23647de575fd90552807260a4b8e0a96ab6afe (diff)
downloadonline_test-a022e0145ec8fb1622d58c2e2281c016b1d45b01.tar.gz
online_test-a022e0145ec8fb1622d58c2e2281c016b1d45b01.tar.bz2
online_test-a022e0145ec8fb1622d58c2e2281c016b1d45b01.zip
Merge pull request #41 from ankitjavalkar/code-server-redesign-mymaster2
Code server redesign
Diffstat (limited to 'testapp/exam/views.py')
-rw-r--r--testapp/exam/views.py186
1 files changed, 133 insertions, 53 deletions
diff --git a/testapp/exam/views.py b/testapp/exam/views.py
index 11aca06..5b7baac 100644
--- a/testapp/exam/views.py
+++ b/testapp/exam/views.py
@@ -14,12 +14,13 @@ from django.db.models import Sum
from django.views.decorators.csrf import csrf_exempt
from taggit.models import Tag
from itertools import chain
+import json
# Local imports.
from testapp.exam.models import Quiz, Question, QuestionPaper, QuestionSet
-from testapp.exam.models import Profile, Answer, AnswerPaper, User
+from testapp.exam.models import Profile, Answer, AnswerPaper, User, TestCase
from testapp.exam.forms import UserRegisterForm, UserLoginForm, QuizForm,\
- QuestionForm, RandomQuestionForm
-from testapp.exam.xmlrpc_clients import code_server
+ QuestionForm, RandomQuestionForm, TestCaseFormSet
+from exam.xmlrpc_clients import code_server
from settings import URL_ROOT
from testapp.exam.models import AssignmentUpload
@@ -281,16 +282,14 @@ def edit_quiz(request):
def edit_question(request):
- """Edit the list of questions seleted by the user for editing."""
+ """Edit the list of questions selected by the user for editing."""
user = request.user
if not user.is_authenticated() or not is_moderator(user):
raise Http404('You are not allowed to view this page!')
-
question_list = request.POST.getlist('questions')
summary = request.POST.getlist('summary')
description = request.POST.getlist('description')
points = request.POST.getlist('points')
- test = request.POST.getlist('test')
options = request.POST.getlist('options')
type = request.POST.getlist('type')
active = request.POST.getlist('active')
@@ -298,14 +297,21 @@ def edit_question(request):
snippet = request.POST.getlist('snippet')
for j, question_id in enumerate(question_list):
question = Question.objects.get(id=question_id)
+ test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question)
+ if test_case_formset.is_valid():
+ test_case_instance = test_case_formset.save(commit=False)
+ for i in test_case_instance:
+ i.save()
+
question.summary = summary[j]
question.description = description[j]
question.points = points[j]
- question.test = test[j]
question.options = options[j]
question.active = active[j]
question.language = language[j]
question.snippet = snippet[j]
+ question.ref_code_path = ref_code_path[j]
+ question.test = test[j]
question.type = type[j]
question.save()
return my_redirect("/exam/manage/questions")
@@ -314,6 +320,16 @@ def edit_question(request):
def add_question(request, question_id=None):
"""To add a new question in the database.
Create a new question and store it."""
+
+ def add_or_delete_test_form(post_request, instance):
+ request_copy = post_request.copy()
+ if 'add_test' in post_request:
+ request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) + 1
+ elif 'delete_test' in post_request:
+ request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) - 1
+ test_case_formset = TestCaseFormSet(request_copy, prefix='test', instance=instance)
+ return test_case_formset
+
user = request.user
ci = RequestContext(request)
if not user.is_authenticated() or not is_moderator(user):
@@ -321,44 +337,88 @@ def add_question(request, question_id=None):
if request.method == "POST":
form = QuestionForm(request.POST)
if form.is_valid():
- data = form.cleaned_data
if question_id is None:
- form.save()
- question = Question.objects.order_by("-id")[0]
- tags = form['tags'].data.split(',')
- for i in range(0, len(tags)-1):
- tag = tags[i].strip()
- question.tags.add(tag)
- return my_redirect("/exam/manage/questions")
+ test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False))
+ if 'save_question' in request.POST:
+ qtn = form.save(commit=False)
+ test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn)
+ form.save()
+ question = Question.objects.order_by("-id")[0]
+ tags = form['tags'].data.split(',')
+ for i in range(0, len(tags)-1):
+ tag = tags[i].strip()
+ question.tags.add(tag)
+ if test_case_formset.is_valid():
+ test_case_formset.save()
+ else:
+ return my_render_to_response('exam/add_question.html',
+ {'form': form,
+ 'formset': test_case_formset},
+ context_instance=ci)
+
+ return my_redirect("/exam/manage/questions")
+
+ return my_render_to_response('exam/add_question.html',
+ {'form': form,
+ 'formset': test_case_formset},
+ context_instance=ci)
+
else:
d = Question.objects.get(id=question_id)
- d.summary = form['summary'].data
- d.description = form['description'].data
- d.points = form['points'].data
- d.test = form['test'].data
- d.options = form['options'].data
- d.type = form['type'].data
- d.active = form['active'].data
- d.language = form['language'].data
- d.snippet = form['snippet'].data
- d.save()
- question = Question.objects.get(id=question_id)
- for tag in question.tags.all():
- question.tags.remove(tag)
- tags = form['tags'].data.split(',')
- for i in range(0, len(tags)-1):
- tag = tags[i].strip()
- question.tags.add(tag)
- return my_redirect("/exam/manage/questions")
+ test_case_formset = add_or_delete_test_form(request.POST, d)
+ if 'save_question' in request.POST:
+ d.summary = form['summary'].data
+ d.description = form['description'].data
+ d.points = form['points'].data
+ d.options = form['options'].data
+ d.type = form['type'].data
+ d.active = form['active'].data
+ d.language = form['language'].data
+ d.snippet = form['snippet'].data
+ d.ref_code_path = form['ref_code_path'].data
+ d.test = form['test'].data
+ d.save()
+ question = Question.objects.get(id=question_id)
+ for tag in question.tags.all():
+ question.tags.remove(tag)
+ tags = form['tags'].data.split(',')
+ for i in range(0, len(tags)-1):
+ tag = tags[i].strip()
+ question.tags.add(tag)
+
+ test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question)
+ if test_case_formset.is_valid():
+ test_case_instance = test_case_formset.save(commit=False)
+ for i in test_case_instance:
+ i.save()
+ else:
+ return my_render_to_response('exam/add_question.html',
+ {'form': form,
+ 'formset': test_case_formset},
+ context_instance=ci)
+
+
+ return my_redirect("/exam/manage/questions")
+ return my_render_to_response('exam/add_question.html',
+ {'form': form,
+ 'formset': test_case_formset},
+ context_instance=ci)
+
else:
+ test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False))
return my_render_to_response('exam/add_question.html',
- {'form': form},
+ {'form': form,
+ 'formset': test_case_formset},
context_instance=ci)
else:
+ form = QuestionForm()
+ test_case_formset = TestCaseFormSet(prefix='test', instance=Question())
if question_id is None:
form = QuestionForm()
+ test_case_formset = TestCaseFormSet(prefix='test', instance=Question())
return my_render_to_response('exam/add_question.html',
- {'form': form},
+ {'form': form,
+ 'formset': test_case_formset},
context_instance=ci)
else:
d = Question.objects.get(id=question_id)
@@ -366,12 +426,13 @@ def add_question(request, question_id=None):
form.initial['summary'] = d.summary
form.initial['description'] = d.description
form.initial['points'] = d.points
- form.initial['test'] = d.test
form.initial['options'] = d.options
form.initial['type'] = d.type
form.initial['active'] = d.active
form.initial['language'] = d.language
form.initial['snippet'] = d.snippet
+ form.initial['ref_code_path'] = d.ref_code_path
+ form.initial['test'] = d.test
form_tags = d.tags.all()
form_tags_split = form_tags.values('name')
initial_tags = ""
@@ -380,8 +441,13 @@ def add_question(request, question_id=None):
if (initial_tags == ","):
initial_tags = ""
form.initial['tags'] = initial_tags
+
+ test_case_formset = TestCaseFormSet(prefix='test',
+ instance=d)
+
return my_render_to_response('exam/add_question.html',
- {'form': form},
+ {'form': form,
+ 'formset': test_case_formset},
context_instance=ci)
@@ -848,6 +914,10 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
if not user.is_authenticated() or paper.end_time < datetime.datetime.now():
return my_redirect('/exam/login/')
question = get_object_or_404(Question, pk=q_id)
+ q_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ paper = AnswerPaper.objects.get(user=request.user, question_paper=q_paper)
+ test_cases = TestCase.objects.filter(question=question)
+
snippet_code = request.POST.get('snippet')
user_code = request.POST.get('answer')
skip = request.POST.get('skip', None)
@@ -876,7 +946,8 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
assign.save()
user_answer = 'ASSIGNMENT UPLOADED'
else:
- user_answer = snippet_code + "\n" + user_code
+ user_code = request.POST.get('answer')
+ user_answer = snippet_code + "\n" + user_code if snippet_code else user_code
new_answer = Answer(question=question, answer=user_answer,
correct=False)
@@ -887,18 +958,20 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
# questions, we obtain the results via XML-RPC with the code executed
# safely in a separate process (the code_server.py) running as nobody.
if not question.type == 'upload':
- correct, success, err_msg = validate_answer(user, user_answer, question)
+ json_data = question.consolidate_answer_data(test_cases, user_answer) \
+ if question.type == 'code' else None
+ correct, result = validate_answer(user, user_answer, question, json_data)
if correct:
new_answer.correct = correct
new_answer.marks = question.points
- new_answer.error = err_msg
+ new_answer.error = result.get('error')
success_msg = True
else:
- new_answer.error = err_msg
+ new_answer.error = result.get('error')
new_answer.save()
time_left = paper.time_left()
- if not success: # Should only happen for non-mcq questions.
+ if not result.get('success'): # Should only happen for non-mcq questions.
if time_left == 0:
reason = 'Your time is up!'
return complete(request, reason, attempt_num, questionpaper_id)
@@ -913,8 +986,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
if old_answer:
old_answer[0].answer = user_code
old_answer[0].save()
- context = {'question': question, 'questions': questions,
- 'error_message': err_msg,
+ context = {'question': question, 'error_message': result.get('error'),
'paper': paper, 'last_attempt': user_code,
'quiz_name': paper.question_paper.quiz.description,
'time_left': time_left, 'to_attempt': to_attempt,
@@ -933,7 +1005,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None):
questionpaper_id, success_msg)
-def validate_answer(user, user_answer, question):
+def validate_answer(user, user_answer, question, json_data=None):
"""
Checks whether the answer submitted by the user is right or wrong.
If right then returns correct = True, success and
@@ -942,9 +1014,9 @@ def validate_answer(user, user_answer, question):
only one attempt are allowed for them.
For code questions success is True only if the answer is correct.
"""
- success = True
+
+ result = {'success': True, 'error': 'Incorrect answer'}
correct = False
- message = 'Incorrect answer'
if user_answer is not None:
if question.type == 'mcq':
@@ -958,11 +1030,12 @@ def validate_answer(user, user_answer, question):
message = 'Correct answer'
elif question.type == 'code':
user_dir = get_user_dir(user)
- success, message = code_server.run_code(user_answer, question.test,
- user_dir, question.language)
- if success:
+ json_result = code_server.run_code(question.language, json_data, user_dir)
+ result = json.loads(json_result)
+ if result.get('success'):
correct = True
- return correct, success, message
+
+ return correct, result
def quit(request, attempt_num=None, questionpaper_id=None):
@@ -1167,18 +1240,20 @@ def show_all_questions(request):
data = request.POST.getlist('question')
forms = []
+ formsets = []
for j in data:
d = Question.objects.get(id=j)
form = QuestionForm()
form.initial['summary'] = d.summary
form.initial['description'] = d.description
form.initial['points'] = d.points
- form.initial['test'] = d.test
form.initial['options'] = d.options
form.initial['type'] = d.type
form.initial['active'] = d.active
form.initial['language'] = d.language
form.initial['snippet'] = d.snippet
+ form.initial['ref_code_path'] = d.ref_code_path
+ form.initial['test'] = d.test
form_tags = d.tags.all()
form_tags_split = form_tags.values('name')
initial_tags = ""
@@ -1188,8 +1263,13 @@ def show_all_questions(request):
initial_tags = ""
form.initial['tags'] = initial_tags
forms.append(form)
+ test_case_formset = TestCaseFormSet(prefix='test', instance=d)
+ formsets.append(test_case_formset)
+ data_list = zip(forms, formsets)
+
return my_render_to_response('exam/edit_question.html',
- {'forms': forms, 'data': data},
+ {'data': data,
+ 'data_list': data_list},
context_instance=ci)
else:
questions = Question.objects.all()