diff options
Diffstat (limited to 'testapp/exam/views.py')
-rw-r--r-- | testapp/exam/views.py | 186 |
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() |