diff options
Diffstat (limited to 'testapp')
-rw-r--r-- | testapp/README.rst | 14 | ||||
-rw-r--r-- | testapp/exam/forms.py | 5 | ||||
-rw-r--r-- | testapp/exam/models.py | 15 | ||||
-rw-r--r-- | testapp/exam/templates/exam/intro.html | 2 | ||||
-rw-r--r-- | testapp/exam/templates/exam/question.html | 42 | ||||
-rw-r--r-- | testapp/exam/templates/exam/quit.html | 4 | ||||
-rw-r--r-- | testapp/exam/urls.py | 35 | ||||
-rw-r--r-- | testapp/exam/views.py | 273 | ||||
-rw-r--r-- | testapp/settings.py | 4 | ||||
-rw-r--r-- | testapp/urls.py | 2 |
10 files changed, 211 insertions, 185 deletions
diff --git a/testapp/README.rst b/testapp/README.rst index f4790a3..e6f8380 100644 --- a/testapp/README.rst +++ b/testapp/README.rst @@ -10,7 +10,7 @@ conduct online test and monitor the test. Quick start ------------ -1. In yourterminal run the following command:: +1. In your terminal run the following command:: $ easy_install git+https://github.com/FOSSEE/online_test.git#egg=django_exam-0.1 2. Add "testapp.exam", "taggit" and "taggit_autocomplete_modified" apps @@ -35,10 +35,14 @@ Quick start 5. Run 'python manage.py syncdb' to create models for the new installed apps. -6. Start the development server and visit http://localhost:8000/exam/ +6. Run 'python manage.py runserver' to start the development server + and visit http://localhost:8000/exam/ -7. In exam app run code_sever command as superuser as follows:: +7. Run code_server command as superuser as follows:: - $ code_server + $ sudo code_server - Note: You must have a sudo access to run the above command. + Note: If you are using virtual python environment, then activate the environment + using sudo. Then simply run the code_server command as follows:: + + $ code_server diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index 843ed15..1f12a3b 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -27,7 +27,7 @@ question_types = ( ("mcq", "Multiple Choice"), ("mcc", "Multiple Correct Choices"), ("code", "Code"), - ("basgn", "Bash Assignment"), + ("upload", "Assignment Upload"), ) UNAME_CHARS = letters + "._" + digits @@ -35,7 +35,6 @@ PWD_CHARS = letters + punctuation + digits attempts = [(i, i) for i in range(1, 6)] attempts.append((-1, 'Infinite')) - days_between_attempts = ((j, j) for j in range(401)) @@ -138,7 +137,7 @@ class QuizForm(forms.Form): super(QuizForm, self).__init__(*args, **kwargs) quizzes = [('', 'Select a prerequisite quiz')] quizzes = quizzes + \ - list(Quiz.objects.values_list('id','description')) + list(Quiz.objects.values_list('id', 'description')) self.fields['prerequisite'] = forms.CharField(required=False, widget=forms.Select(choices=quizzes)) diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 0ad6021..72fb51b 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -30,11 +30,10 @@ question_types = ( ("mcq", "Multiple Choice"), ("mcc", "Multiple Correct Choices"), ("code", "Code"), - ("basgn", "Bash Assignment"), + ("upload", "Assignment Upload"), ) attempts = [(i, i) for i in range(1, 6)] attempts.append((-1, 'Infinite')) - days_between_attempts = ((j, j) for j in range(401)) test_status = ( @@ -42,9 +41,11 @@ test_status = ( ('completed', 'Completed'), ) + def get_assignment_dir(instance, filename): return '%s/%s' % (instance.user.roll_number, instance.assignmentQuestion.id) + ############################################################################### class Question(models.Model): """Question for a quiz.""" @@ -192,9 +193,9 @@ class QuestionPaper(models.Model): questions += question_set.get_random_questions() return questions - def make_answerpaper(self, user, ip, attempt_no): + def make_answerpaper(self, user, ip, attempt_num): """Creates an answer paper for the user to attempt the quiz""" - ans_paper = AnswerPaper(user=user, user_ip=ip, attempt_number=attempt_no) + ans_paper = AnswerPaper(user=user, user_ip=ip, attempt_number=attempt_num) ans_paper.start_time = datetime.datetime.now() ans_paper.end_time = ans_paper.start_time \ + datetime.timedelta(minutes=self.quiz.duration) @@ -361,7 +362,7 @@ class AnswerPaper(models.Model): Checks whether student passed or failed, as per the quiz passing criteria. """ - if self.percent is not None: + if self.percent is not None: if self.percent >= self.question_paper.quiz.pass_criteria: self.passed = True else: @@ -388,9 +389,9 @@ class AnswerPaper(models.Model): def __unicode__(self): u = self.user return u'Question paper for {0} {1}'.format(u.first_name, u.last_name) - -################################################################################ + +############################################################################### class AssignmentUpload(models.Model): user = models.ForeignKey(Profile) assignmentQuestion = models.ForeignKey(Question) diff --git a/testapp/exam/templates/exam/intro.html b/testapp/exam/templates/exam/intro.html index 58068ed..592937a 100644 --- a/testapp/exam/templates/exam/intro.html +++ b/testapp/exam/templates/exam/intro.html @@ -27,7 +27,7 @@ </ul> <p> We hope you enjoy taking this exam !!!</p> - <form action="{{URL_ROOT}}/exam/start/{{ attempt_no }}/{{ paper_id }}/" method="post" align="center"> + <form action="{{URL_ROOT}}/exam/start/{{ attempt_num }}/{{ paper_id }}/" method="post" align="center"> {% csrf_token %} <center><button class="btn" type="submit" name="start">Start Exam!</button></center> </form> diff --git a/testapp/exam/templates/exam/question.html b/testapp/exam/templates/exam/question.html index 5d03b37..eac6792 100644 --- a/testapp/exam/templates/exam/question.html +++ b/testapp/exam/templates/exam/question.html @@ -10,7 +10,10 @@ {% endblock %} {% block script %} +<script src="/static/taggit_autocomplete_modified/jquery.min.js" type="text/javascript"></script> +<script src="/static/taggit_autocomplete_modified/jquery.autocomplete.js" type="text/javascript"></script> <script src="{{ URL_ROOT }}/static/exam/js/question.js"></script> +<script src="{{ URL_ROOT }}/static/exam/js/bootstrap-modal.js"></script> <script> var time_left = {{ time_left }} @@ -48,12 +51,26 @@ function setSnippetHeight() ta.style.height = height; autoresize(); } + +function validate(){ + uploaded_file = document.getElementById("assignment").value; + if(uploaded_file == ""){ + $("#upload_alert").modal("show"); + return false; + } + else + { + return true; + } +} + function call_skip(url) { form = document.forms["code"] form.action = url form.submit(); } + </script> {% endblock script %} @@ -121,7 +138,7 @@ function call_skip(url) </div>{% endif %} <p id="status"></p> - + <form id="code" action="{{URL_ROOT}}/exam/{{ question.id }}/check/{{ paper.attempt_number }}/{{ paper.question_paper.id }}/" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type=hidden name="question_id" id="question_id" value={{ question.id }}></input> @@ -131,7 +148,7 @@ function call_skip(url) <input name="answer" type="radio" value="{{option}}" />{{option}} <br/> {% endfor %} {% endif %} - {% if question.type == "basgn" %} + {% if question.type == "upload" %} <p>Upload assignment file for the said question<p> <input type=file id="assignment" name="assignment"> <hr> @@ -157,8 +174,8 @@ function call_skip(url) {% if question.type == "mcq" or question.type == "mcc "%} <br><button class="btn" type="submit" name="check" id="check">Submit Answer</button> - {% elif question.type == "basgn" %} - <br><button class="btn" type="submit" name="check" id="check">Submit Answer</button> + {% elif question.type == "upload" %} + <br><button class="btn" type="submit" name="check" id="check" onClick="return validate();">Upload</button> {% else %} <button class="btn" type="submit" name="check" id="check" onClick="submitCode();">Check Answer</button> {% endif %} @@ -166,4 +183,21 @@ function call_skip(url) </form> + <!-- Modal --> + <div class="modal fade " id="upload_alert" > + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">File not selected</h4> + </div> + <div id = "modal_body"class="modal-body"> + <font color="brown"><b>Kindly attach a file and then click upload.</b></font> + </div> + <div class="modal-footer"> + <button type="button" class="btn primary close" data-dismiss="modal">OK</button> + </div> + </div> + </div> + </div> + {% endblock content %} diff --git a/testapp/exam/templates/exam/quit.html b/testapp/exam/templates/exam/quit.html index 2c347cb..f49b62f 100644 --- a/testapp/exam/templates/exam/quit.html +++ b/testapp/exam/templates/exam/quit.html @@ -7,8 +7,8 @@ <center><h4>Your current answers are saved.</h4></center> <center><h4> Are you sure you wish to quit the exam?</h4></center> <center><h4> Be sure, as you won't be able to restart this exam.</h4></center> - <form action="{{URL_ROOT}}/exam/complete/{{ attempt_no }}/{{ id }}/" method="post"> + <form action="{{URL_ROOT}}/exam/complete/{{ attempt_num }}/{{ id }}/" method="post"> {% csrf_token %} - <center><button class="btn" type="submit" name="yes">Yes!</button> <button class="btn" type="button" name="no" onClick="window.location='{{ URL_ROOT }}/exam/start/{{ attempt_no }}/{{ id }}/'">No!</button></center> + <center><button class="btn" type="submit" name="yes">Yes!</button> <button class="btn" type="button" name="no" onClick="window.location='{{ URL_ROOT }}/exam/start/{{ attempt_num }}/{{ id }}/'">No!</button></center> </form> {% endblock content %} diff --git a/testapp/exam/urls.py b/testapp/exam/urls.py index 62fa9e1..43970ce 100644 --- a/testapp/exam/urls.py +++ b/testapp/exam/urls.py @@ -1,23 +1,24 @@ -from django.conf.urls import * +from django.conf.urls import patterns, url urlpatterns = patterns('testapp.exam.views', url(r'^$', 'index'), url(r'^login/$', 'user_login'), - url(r'^quizzes/$','quizlist_user'), - url(r'^results/$','results_user'), + url(r'^quizzes/$', 'quizlist_user'), + url(r'^results/$', 'results_user'), url(r'^start/$', 'start'), - url(r'^start/(?P<attempt_no>\d+)/(?P<questionpaper_id>\d+)/$','start'), - url(r'^quit/(?P<attempt_no>\d+)/(?P<questionpaper_id>\d+)/$', 'quit'), - url(r'^intro/(?P<questionpaper_id>\d+)/$','intro'), + url(r'^start/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'start'), + url(r'^quit/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'quit'), + url(r'^intro/(?P<questionpaper_id>\d+)/$', 'intro'), url(r'^complete/$', 'complete'), - url(r'^complete/(?P<attempt_no>\d+)/(?P<questionpaper_id>\d+)/$', 'complete'), - url(r'^submit-assignment(?P<question_id>\d+)/$', 'submit_assignment'), + url(r'^complete/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',\ + 'complete'), url(r'^register/$', 'user_register'), url(r'^(?P<q_id>\d+)/$', 'question'), url(r'^(?P<q_id>\d+)/check/$', 'check'), - url(r'^(?P<q_id>\d+)/check/(?P<attempt_no>\d+)/(?P<questionpaper_id>\d+)/$', 'check'), + url(r'^(?P<q_id>\d+)/check/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',\ + 'check'), url(r'^intro/$', 'start'), - url(r'^(?P<q_id>\d+)/(?P<attempt_no>\d+)/(?P<questionpaper_id>\d+)/$', 'show_question'), + url(r'^(?P<q_id>\d+)/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$', 'show_question'), url(r'^manage/$', 'prof_manage'), url(r'^manage/addquestion/$', 'add_question'), @@ -27,22 +28,22 @@ urlpatterns = patterns('testapp.exam.views', url(r'^manage/editquestion/$', 'edit_question'), url(r'^manage/addquiz/(?P<quiz_id>\d+)/$', 'add_quiz'), url(r'^manage/gradeuser/$', 'show_all_users'), - url(r'^manage/gradeuser/(?P<username>[a-zA-Z0-9_.]+)/$', 'grade_user'), + url(r'^manage/gradeuser/(?P<username>.*)/$', 'grade_user'), url(r'^manage/questions/$', 'show_all_questions'), - url(r'^manage/showquiz/$','show_all_quiz'), + url(r'^manage/showquiz/$', 'show_all_quiz'), url(r'^manage/monitor/$', 'monitor'), - url(r'^manage/showquestionpapers/$','show_all_questionpapers'), + url(r'^manage/showquestionpapers/$', 'show_all_questionpapers'), url(r'^manage/showquestionpapers/(?P<questionpaper_id>\d+)/$',\ 'show_all_questionpapers'), url(r'^manage/monitor/(?P<questionpaper_id>\d+)/$', 'monitor'), - url(r'^manage/user_data/(?P<username>[a-zA-Z0-9_.]+)/$','user_data'), - url(r'^manage/designquestionpaper/$','design_questionpaper'), + url(r'^manage/user_data/(?P<username>.*)/$', 'user_data'), + url(r'^manage/designquestionpaper/$', 'design_questionpaper'), url(r'^manage/designquestionpaper/(?P<questionpaper_id>\d+)/$',\ 'design_questionpaper'), url(r'^manage/designquestionpaper/automatic/(?P<questionpaper_id>\d+)/$',\ 'automatic_questionpaper'), - url(r'^manage/designquestionpaper/automatic$','automatic_questionpaper'), - url(r'^manage/designquestionpaper/manual$','manual_questionpaper'), + url(r'^manage/designquestionpaper/automatic$', 'automatic_questionpaper'), + url(r'^manage/designquestionpaper/manual$', 'manual_questionpaper'), url(r'^manage/designquestionpaper/manual/(?P<questionpaper_id>\d+)/$',\ 'manual_questionpaper'), url(r'^ajax/questionpaper/(?P<query>.+)/$', 'ajax_questionpaper'), diff --git a/testapp/exam/views.py b/testapp/exam/views.py index f4826a6..11aca06 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -165,7 +165,6 @@ def intro(request, questionpaper_id): quest_paper = QuestionPaper.objects.get(id=questionpaper_id) attempt_number = quest_paper.quiz.attempts_allowed time_lag = quest_paper.quiz.time_between_attempts - if quest_paper.quiz.prerequisite: try: pre_quest = QuestionPaper.objects.get( @@ -186,42 +185,35 @@ def intro(request, questionpaper_id): already_attempted = attempted_papers.count() if already_attempted == 0: context = {'user': user, 'paper_id': questionpaper_id,\ - 'attempt_no': already_attempted + 1} + 'attempt_num': already_attempted + 1} return my_render_to_response('exam/intro.html', context, context_instance=ci) + if already_attempted == attempt_number: - previous_attempt = attempted_papers[already_attempted-1] - previous_attempt_day = previous_attempt.start_time - today = datetime.datetime.today() - if previous_attempt.status == 'inprogress': - end_time = previous_attempt.end_time - quiz_time = previous_attempt.question_paper.quiz.duration*60 - if quiz_time > (today-previous_attempt_day).seconds: - return show_question(request, - previous_attempt.current_question(), - previous_attempt.attempt_number, - previous_attempt.question_paper.id) - else: - return my_redirect("/exam/quizzes") + inprogress, previous_attempt = _check_previous_attempt(attempted_papers, + already_attempted) + if inprogress: + return show_question(request, + previous_attempt.current_question(), + previous_attempt.attempt_number, + previous_attempt.question_paper.id) else: - return my_redirect("/exam/quizzes/") + return my_redirect("/exam/quizzes") + if already_attempted < attempt_number or attempt_number < 0: - previous_attempt = attempted_papers[already_attempted-1] - previous_attempt_day = previous_attempt.start_time - today = datetime.datetime.today() - if previous_attempt.status == 'inprogress': - end_time = previous_attempt.end_time - quiz_time = previous_attempt.question_paper.quiz.duration*60 - if quiz_time > (today-previous_attempt_day).seconds: - return show_question(request, - previous_attempt.current_question(), - previous_attempt.attempt_number, - previous_attempt.question_paper.id) - days_after_attempt = (today - previous_attempt_day).days + inprogress, previous_attempt = _check_previous_attempt(attempted_papers, + already_attempted) + if inprogress: + return show_question(request, + previous_attempt.current_question(), + previous_attempt.attempt_number, + previous_attempt.question_paper.id) + days_after_attempt = (datetime.datetime.today() - \ + previous_attempt.start_time).days if days_after_attempt >= time_lag: context = {'user': user, 'paper_id': questionpaper_id,\ - 'attempt_no': already_attempted + 1} + 'attempt_num': already_attempted + 1} return my_render_to_response('exam/intro.html', context, context_instance=ci) else: @@ -230,6 +222,20 @@ def intro(request, questionpaper_id): return my_redirect("/exam/quizzes/") +def _check_previous_attempt(attempted_papers, already_attempted): + previous_attempt = attempted_papers[already_attempted-1] + previous_attempt_day = previous_attempt.start_time + today = datetime.datetime.today() + if previous_attempt.status == 'inprogress': + end_time = previous_attempt.end_time + quiz_time = previous_attempt.question_paper.quiz.duration*60 + if quiz_time > (today-previous_attempt_day).seconds: + return True, previous_attempt + else: + return False, previous_attempt + else: + return False, previous_attempt + def results_user(request): """Show list of Results of Quizzes that is taken by logged-in user.""" user = request.user @@ -644,8 +650,10 @@ rights/permissions and log in.""" users_per_paper = [] for paper in question_papers: answer_papers = AnswerPaper.objects.filter(question_paper=paper) - users_passed = AnswerPaper.objects.filter(question_paper=paper, passed=True).count() - users_failed = AnswerPaper.objects.filter(question_paper=paper, passed=False).count() + users_passed = AnswerPaper.objects.filter(question_paper=paper, + passed=True).count() + users_failed = AnswerPaper.objects.filter(question_paper=paper, + passed=False).count() temp = paper, answer_papers, users_passed, users_failed users_per_paper.append(temp) context = {'user': user, 'users_per_paper': users_per_paper} @@ -682,7 +690,7 @@ def user_login(request): context_instance=ci) -def start(request, attempt_no=None, questionpaper_id=None): +def start(request, attempt_num=None, questionpaper_id=None): """Check the user cedentials and if any quiz is available, start the exam.""" user = request.user @@ -695,13 +703,13 @@ def start(request, attempt_no=None, questionpaper_id=None): except QuestionPaper.DoesNotExist: msg = 'Quiz not found, please contact your '\ 'instructor/administrator. Please login again thereafter.' - return complete(request, msg, attempt_no, questionpaper_id) + return complete(request, msg, attempt_num, questionpaper_id) try: old_paper = AnswerPaper.objects.get( - question_paper=questionpaper, user=user, attempt_number=attempt_no) + question_paper=questionpaper, user=user, attempt_number=attempt_num) q = old_paper.current_question() - return show_question(request, q, attempt_no, questionpaper_id) + return show_question(request, q, attempt_num, questionpaper_id) except AnswerPaper.DoesNotExist: ip = request.META['REMOTE_ADDR'] key = gen_key(10) @@ -711,13 +719,43 @@ def start(request, attempt_no=None, questionpaper_id=None): msg = 'You do not have a profile and cannot take the quiz!' raise Http404(msg) - new_paper = questionpaper.make_answerpaper(user, ip, attempt_no) + new_paper = questionpaper.make_answerpaper(user, ip, attempt_num) # Make user directory. user_dir = get_user_dir(user) - return start(request, attempt_no, questionpaper_id) + return start(request, attempt_num, questionpaper_id) + + +def get_questions(paper): + ''' + Takes answerpaper as an argument. Returns the total questions as + ordered dictionary, the questions yet to attempt and the questions + attempted + ''' + to_attempt = [] + submitted = [] + all_questions = [] + questions = {} + if paper.questions: + to_attempt = (paper.questions).split('|') + if paper.questions_answered: + submitted = (paper.questions_answered).split('|') + if not to_attempt: + submitted.sort() + all_questions = submitted + if not submitted: + to_attempt.sort() + all_questions = to_attempt + if to_attempt and submitted: + q_append = to_attempt + submitted + q_append.sort() + all_questions = q_append + for num, value in enumerate(all_questions, 1): + questions[value] = num + questions = collections.OrderedDict(sorted(questions.items())) + return questions, to_attempt, submitted -def question(request, q_id, attempt_no, questionpaper_id, success_msg=None): +def question(request, q_id, attempt_num, questionpaper_id, success_msg=None): """Check the credentials of the user and start the exam.""" user = request.user @@ -727,7 +765,7 @@ def question(request, q_id, attempt_no, questionpaper_id, success_msg=None): try: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get( - user=request.user, attempt_number=attempt_no, question_paper=q_paper) + user=request.user, attempt_number=attempt_num, question_paper=q_paper) except AnswerPaper.DoesNotExist: return my_redirect('/exam/start/') if not paper.question_paper.quiz.active: @@ -740,35 +778,16 @@ def question(request, q_id, attempt_no, questionpaper_id, success_msg=None): if time_left == 0: return complete(request, reason='Your time is up!') quiz_name = paper.question_paper.quiz.description - to_attempt = [] - submitted = [] - if paper.questions: - to_attempt = (paper.questions).split('|') - if paper.questions_answered: - submitted = (paper.questions_answered).split('|') - all_questions = [] - if not to_attempt: - submitted.sort() - all_questions = submitted - if not submitted: - to_attempt.sort() - all_questions = to_attempt - if to_attempt and submitted: - q_append = to_attempt + submitted - q_append.sort() - all_questions = q_append - questions = {} - for num, value in enumerate(all_questions, 1): - questions[value] = num - questions = collections.OrderedDict(sorted(questions.items())) + questions, to_attempt, submitted = get_questions(paper) if success_msg is None: - context = {'question': q, 'questions' : questions, 'paper': paper, + context = {'question': q, 'questions': questions, 'paper': paper, 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, - 'to_attempt' : to_attempt, 'submitted': submitted} + 'to_attempt': to_attempt, 'submitted': submitted} else: - context = {'question': q, 'questions' : questions, 'paper': paper, + context = {'question': q, 'questions': questions, 'paper': paper, 'user': user, 'quiz_name': quiz_name, 'time_left': time_left, - 'success_msg': success_msg, 'to_attempt' : to_attempt, 'submitted' : submitted} + 'success_msg': success_msg, 'to_attempt': to_attempt, + 'submitted': submitted} if q.type == 'code': skipped_answer = paper.answers.filter(question=q, skipped=True) if skipped_answer: @@ -778,48 +797,53 @@ def question(request, q_id, attempt_no, questionpaper_id, success_msg=None): context_instance=ci) -def show_question(request, q_id, attempt_no, questionpaper_id, success_msg=None): +def show_question(request, q_id, attempt_num, questionpaper_id, success_msg=None): """Show a question if possible.""" user = request.user q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_no, + paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, question_paper=q_paper) if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): return my_redirect('/exam/login/') old_qid = request.POST.get('question_id') if old_qid is not None: - quest = Question.objects.get(pk=old_qid) user_code = request.POST.get('answer') if quest.type == 'code': - user_answer = user_code # not taking snippet here. old_skipped = paper.answers.filter(question=quest, skipped=True) - if old_skipped: - skipped_answer = old_skipped[0] - skipped_answer.answer=user_answer - skipped_answer.save() - else: - skipped_answer = Answer(question=quest, answer=user_answer, - correct=False, skipped=True) - skipped_answer.save() - paper.answers.add(skipped_answer) + _save_skipped_answer(old_skipped, user_code, paper, quest) if len(q_id) == 0: msg = 'Congratulations! You have successfully completed the quiz.' - return complete(request, msg, attempt_no, questionpaper_id) + return complete(request, msg, attempt_num, questionpaper_id) else: - return question(request, q_id, attempt_no, questionpaper_id, success_msg) + return question(request, q_id, attempt_num, questionpaper_id, success_msg) + +def _save_skipped_answer(old_skipped, user_answer, paper, question): + """ + Saves the answer on skip. Only the code questions are saved. + Snippet is not saved with the answer. + """ + if old_skipped: + skipped_answer = old_skipped[0] + skipped_answer.answer=user_answer + skipped_answer.save() + else: + skipped_answer = Answer(question=question, answer=user_answer, + correct=False, skipped=True) + skipped_answer.save() + paper.answers.add(skipped_answer) -def check(request, q_id, attempt_no=None, questionpaper_id=None): +def check(request, q_id, attempt_num=None, questionpaper_id=None): """Checks the answers of the user for particular question""" user = request.user q_paper = QuestionPaper.objects.get(id=questionpaper_id) - paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_no, + paper = AnswerPaper.objects.get(user=request.user, attempt_number=attempt_num, question_paper=q_paper) if q_id in paper.questions_answered: next_q = paper.skip() - return show_question(request, next_q, attempt_no, questionpaper_id) + return show_question(request, next_q, attempt_num, questionpaper_id) if not user.is_authenticated() or paper.end_time < datetime.datetime.now(): return my_redirect('/exam/login/') @@ -831,30 +855,24 @@ def check(request, q_id, attempt_no=None, questionpaper_id=None): success = True if skip is not None: if question.type == 'code': - user_answer = user_code # not taking snippet here. old_skipped = paper.answers.filter(question=question, skipped=True) - if old_skipped: - skipped_answer = old_skipped[0] - skipped_answer.answer=user_answer - skipped_answer.save() - else: - skipped_answer = Answer(question=question, answer=user_answer, - correct=False, skipped=True) - skipped_answer.save() - paper.answers.add(skipped_answer) + _save_skipped_answer(old_skipped, user_code, paper, question) next_q = paper.skip() - return show_question(request, next_q, attempt_no, questionpaper_id) + return show_question(request, next_q, attempt_num, questionpaper_id) # Add the answer submitted, regardless of it being correct or not. if question.type == 'mcq': user_answer = request.POST.get('answer') elif question.type == 'mcc': user_answer = request.POST.getlist('answer') - elif question.type == 'basgn': + elif question.type == 'upload': assign = AssignmentUpload() assign.user = user.profile assign.assignmentQuestion = question - assign.assignmentFile = request.FILES['assignment'] + # if time-up at upload question then the form is submitted without + # validation + if 'assignment' in request.FILES: + assign.assignmentFile = request.FILES['assignment'] assign.save() user_answer = 'ASSIGNMENT UPLOADED' else: @@ -868,7 +886,7 @@ def check(request, q_id, attempt_no=None, questionpaper_id=None): # If we were not skipped, we were asked to check. For any non-mcq # 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 == 'basgn': + if not question.type == 'upload': correct, success, err_msg = validate_answer(user, user_answer, question) if correct: new_answer.correct = correct @@ -883,31 +901,14 @@ def check(request, q_id, attempt_no=None, questionpaper_id=None): if not success: # Should only happen for non-mcq questions. if time_left == 0: reason = 'Your time is up!' - return complete(request, reason, attempt_no, questionpaper_id) + return complete(request, reason, attempt_num, questionpaper_id) if not paper.question_paper.quiz.active: reason = 'The quiz has been deactivated!' - return complete(request, reason, attempt_no, questionpaper_id) - to_attempt = [] - submitted = [] - if paper.questions: - to_attempt = (paper.questions).split('|') - if paper.questions_answered: - submitted = (paper.questions_answered).split('|') - all_questions = [] - if not to_attempt: - submitted.sort() - all_questions = submitted - if not submitted: - to_attempt.sort() - all_questions = to_attempt - if to_attempt and submitted: - q_append = to_attempt + submitted - q_append.sort() - all_questions = q_append - questions = {} - for num, value in enumerate(all_questions, 1): - questions[value] = num - questions = collections.OrderedDict(sorted(questions.items())) + return complete(request, reason, attempt_num, questionpaper_id) + if not paper.question_paper.quiz.active: + reason = 'The quiz has been deactivated!' + return complete(request, reason, attempt_num, questionpaper_id) + questions, to_attempt, submitted = get_questions(paper) old_answer = paper.answers.filter(question=question, skipped=True) if old_answer: old_answer[0].answer = user_code @@ -916,7 +917,8 @@ def check(request, q_id, attempt_no=None, questionpaper_id=None): 'error_message': err_msg, 'paper': paper, 'last_attempt': user_code, 'quiz_name': paper.question_paper.quiz.description, - 'time_left': time_left, 'to_attempt' : to_attempt, 'submitted': submitted} + 'time_left': time_left, 'to_attempt': to_attempt, + 'submitted': submitted} ci = RequestContext(request) return my_render_to_response('exam/question.html', context, @@ -924,10 +926,10 @@ def check(request, q_id, attempt_no=None, questionpaper_id=None): else: if time_left <= 0: reason = 'Your time is up!' - return complete(request, reason, attempt_no, questionpaper_id) + return complete(request, reason, attempt_num, questionpaper_id) else: next_q = paper.completed_question(question.id) - return show_question(request, next_q, attempt_no, + return show_question(request, next_q, attempt_num, questionpaper_id, success_msg) @@ -963,15 +965,15 @@ def validate_answer(user, user_answer, question): return correct, success, message -def quit(request, attempt_no=None, questionpaper_id=None): +def quit(request, attempt_num=None, questionpaper_id=None): """Show the quit page when the user logs out.""" context = {'id': questionpaper_id, - 'attempt_no': attempt_no} + 'attempt_num': attempt_num} return my_render_to_response('exam/quit.html', context, context_instance=RequestContext(request)) -def complete(request, reason=None, attempt_no=None, questionpaper_id=None): +def complete(request, reason=None, attempt_num=None, questionpaper_id=None): """Show a page to inform user that the quiz has been compeleted.""" user = request.user @@ -983,7 +985,7 @@ def complete(request, reason=None, attempt_no=None, questionpaper_id=None): else: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get(user=user, question_paper=q_paper, - attempt_number=attempt_no) + attempt_number=attempt_num) paper.update_marks_obtained() paper.update_percent() paper.update_passed() @@ -1297,7 +1299,8 @@ def design_questionpaper(request): question_paper.fixed_questions.add(question_id) if random_questions: for random_question, num in zip(random_questions, random_number): - question = Question.objects.get(id=random_question[0]) + qid = random_question.split(',')[0] + question = Question.objects.get(id=int(qid)) marks = question.points question_set = QuestionSet(marks=marks, num_questions=num) question_set.save() @@ -1312,19 +1315,3 @@ def design_questionpaper(request): context = {'form': form} return my_render_to_response('exam/design_questionpaper.html', context, context_instance=ci) - - -def submit_assignment(request, question_id=None): - user = request.user - skip = request.POST.get('skip', None) - if request.method == "POST" and skip is not None: - question = Question.objects.get(id=question_id) - assignment = AssignmentUpload() - assignment.user = user - assignment.assignmentQuestion = question - assignment.assignmentFile = request.FILES['assignment'] - assignment.save() - #next question ke liye code idhar - else: - #code for skipping the question - pass diff --git a/testapp/settings.py b/testapp/settings.py index 00a6b17..88d4a5a 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -72,12 +72,12 @@ USE_L10N = True # Absolute filesystem path to the directory that will hold user-uploaded files. # Example: "/home/media/media.lawrence.com/media/" -MEDIA_ROOT = join(CURDIR, '../uploads') +MEDIA_ROOT = '' # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash. # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" -MEDIA_URL = 'upload/' +MEDIA_URL = '' # Absolute path to the directory static files should be collected to. # Don't put anything in this directory yourself; store your static files diff --git a/testapp/urls.py b/testapp/urls.py index dee297c..0d126f4 100644 --- a/testapp/urls.py +++ b/testapp/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import * +from django.conf.urls import patterns, include, url # Uncomment the next two lines to enable the admin: from django.contrib import admin |