diff options
author | Prabhu Ramachandran | 2011-11-21 02:41:27 +0530 |
---|---|---|
committer | Prabhu Ramachandran | 2011-11-21 02:41:27 +0530 |
commit | c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa (patch) | |
tree | 6109a8f027139e8d86d58bc0cb6f147b29c31d9c | |
parent | 8f7b25c5639dbe7912df35ea94dfb665d74d0107 (diff) | |
download | online_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.tar.gz online_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.tar.bz2 online_test-c2185243e9e3e8a66a2a4c7a549d9bc00fd9f2fa.zip |
ENH: Better monitor reporting and user_data info
This checkin adds the following:
- /exam/monitor displays all available quizzes.
- /exam/monitor/quiz_id displays results for the specified quiz.
- /exam/user_data/username displays the users data including answers.
- A link is provided in monitor output to see user data.
- More monitor data like number of attempts.
- The monitor and user data are only shown for a user who is
authenticated and is staff.
-rw-r--r-- | exam/urls.py | 2 | ||||
-rw-r--r-- | exam/views.py | 112 | ||||
-rw-r--r-- | templates/exam/monitor.html | 41 | ||||
-rw-r--r-- | templates/exam/user_data.html | 38 |
4 files changed, 178 insertions, 15 deletions
diff --git a/exam/urls.py b/exam/urls.py index e517adb..129a83f 100644 --- a/exam/urls.py +++ b/exam/urls.py @@ -8,6 +8,8 @@ urlpatterns = patterns('exam.views', url(r'^quit/$', 'quit'), url(r'^complete/$', 'complete'), url(r'^monitor/$', 'monitor'), + url(r'^monitor/(?P<quiz_id>\d+)/$', 'monitor'), + url(r'^user_data/(?P<username>[a-zA-Z0-9_.]+)/$', 'user_data'), url(r'^(?P<q_id>\d+)/$', 'question'), url(r'^(?P<q_id>\d+)/check/$', 'check'), ) diff --git a/exam/views.py b/exam/views.py index 0bec977..7f1f7cf 100644 --- a/exam/views.py +++ b/exam/views.py @@ -8,7 +8,10 @@ import datetime from django.contrib.auth import login, logout, authenticate from django.shortcuts import render_to_response, get_object_or_404, redirect from django.template import RequestContext -from exam.models import Quiz, Question, QuestionPaper, Profile, Answer +from django.http import Http404 + +# Local imports. +from exam.models import Quiz, Question, QuestionPaper, Profile, Answer, User from exam.forms import UserRegisterForm, UserLoginForm from exam.xmlrpc_clients import python_server from settings import URL_ROOT @@ -150,7 +153,10 @@ def question(request, q_id): try: paper = QuestionPaper.objects.get(user=request.user) except QuestionPaper.DoesNotExist: - my_redirect('/exam/start') + return my_redirect('/exam/start') + if not paper.quiz.active: + return complete(request, reason='The quiz has been deactivated!') + time_left = paper.time_left() if time_left == 0: return complete(request, reason='Your time is up!') @@ -204,6 +210,8 @@ def check(request, q_id): time_left = paper.time_left() if time_left == 0: return complete(request, reason='Your time is up!') + if not paper.quiz.active: + return complete(request, reason='The quiz has been deactivated!') context = {'question': question, 'error_message': err_msg, 'paper': paper, 'last_attempt': answer, @@ -234,13 +242,36 @@ def complete(request, reason=None): else: return my_redirect('/exam/') -def monitor(request): +def monitor(request, quiz_id=None): """Monitor the progress of the papers taken so far.""" - q_papers = QuestionPaper.objects.all() - questions = Question.objects.all() - # Mapping from question id to points - marks = dict( ( (q.id, q.points) for q in questions) ) - paper_list = [] + user = request.user + if not user.is_authenticated() and not user.is_staff: + raise Http404('You are not allowed to view this page!') + + if quiz_id is None: + quizzes = Quiz.objects.all() + quiz_data = {} + for quiz in quizzes: + quiz_data[quiz.id] = quiz.description + context = {'paper_list': [], + 'quiz_name': '', + 'quiz_data':quiz_data} + return my_render_to_response('exam/monitor.html', context, + context_instance=RequestContext(request)) + + quiz_data = {} + try: + quiz = Quiz.objects.get(active=True) + except Quiz.DoesNotExist: + q_papers = [] + quiz = None + else: + q_papers = QuestionPaper.objects.filter(quiz=quiz) + questions = Question.objects.all() + # Mapping from question id to points + marks = dict( ( (q.id, q.points) for q in questions) ) + + paper_list = [] for q_paper in q_papers: paper = {} user = q_paper.user @@ -249,18 +280,79 @@ def monitor(request): except Profile.DoesNotExist: # Admin user may have a paper by accident but no profile. continue - paper['username'] = str(user.first_name) + ' ' + str(user.last_name) + paper['name'] = user.get_full_name() + paper['username'] = user.username paper['rollno'] = str(profile.roll_number) qa = q_paper.questions_answered.split('|') answered = ', '.join(sorted(qa)) paper['answered'] = answered if answered else 'None' + paper['attempts'] = q_paper.answers.count() total = sum( [marks[int(id)] for id in qa if id] ) paper['total'] = total paper_list.append(paper) + if quiz is None: + quiz_name = 'No active quiz' + elif len(quiz.description) > 0: + quiz_name = quiz.description + else: + quiz_name = 'Quiz' + paper_list.sort(cmp=lambda x, y: cmp(x['total'], y['total']), reverse=True) - context = {'paper_list': paper_list} + context = {'paper_list': paper_list, 'quiz_name': quiz_name} return my_render_to_response('exam/monitor.html', context, context_instance=RequestContext(request)) + +def user_data(request, username): + current_user = request.user + if not current_user.is_authenticated() and not current_user.is_staff: + raise Http404('You are not allowed to view this page!') + + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + q_papers = [] + else: + q_papers = QuestionPaper.objects.filter(user=user) + questions = Question.objects.all() + # Mapping from question id to points + marks = dict( ( (q.id, q.points) for q in questions) ) + + data = {} + try: + profile = Profile.objects.get(user=user) + except Profile.DoesNotExist: + # Admin user may have a paper by accident but no profile. + profile = None + data['username'] = user.username + data['email'] = user.email + data['rollno'] = profile.roll_number if profile else '' + data['name'] = user.get_full_name() + papers = [] + for q_paper in q_papers: + paper = {} + paper['name'] = q_paper.quiz.description + qa = q_paper.questions_answered.split('|') + answered = ', '.join(sorted(qa)) + paper['answered'] = answered if answered else 'None' + paper['attempts'] = q_paper.answers.count() + total = sum( [marks[int(id)] for id in qa if id] ) + paper['total'] = total + answers = {} + for answer in q_paper.answers.all(): + qs = answer.question.summary + code = '#'*80 + '\n' + str(answer.answer) + '\n' + if qs in answers: + answers[qs] += code + else: + answers[qs] = code + paper['answers'] = answers + papers.append(paper) + data['papers'] = papers + + context = {'user_data': data} + return my_render_to_response('exam/user_data.html', context, + context_instance=RequestContext(request)) +
\ No newline at end of file diff --git a/templates/exam/monitor.html b/templates/exam/monitor.html index d79bb35..201e5db 100644 --- a/templates/exam/monitor.html +++ b/templates/exam/monitor.html @@ -5,26 +5,57 @@ {% block meta %} <meta http-equiv="refresh" content="30"/> {% endblock meta %} {% block content %} -<h1> Current quiz results </h1> +{% if not quiz_data and not paper_list %} +<h1> Quiz results </h1> +<p> No quizzes available. </p> + +{% endif %} + +{# ############################################################### #} +{# This is rendered when we are just viewing exam/monitor #} +{% if quiz_data %} +<h1> Available quizzes </h1> + +<ul> +{% for quiz_id, quiz_name in quiz_data.items %} +<li><a href="{{URL_ROOT}}/exam/monitor/{{quiz_id}}/">{{ quiz_name }}</a></li> +{% endfor %} +</ul> +{% endif %} + +{# ############################################################### #} +{# This is rendered when we are just viewing exam/monitor/quiz_num #} {% if paper_list %} +<h1> {{ quiz_name }} results </h1> + +{# <p> Quiz: {{ quiz_name }}</p> #} +<p>Number of papers: {{ paper_list|length }} </p> + <table border="1" cellpadding="3"> <tr> - <th>Student </th> <th> Roll number </th> <th>Questions answered</th> <th>Total marks</th> + <th> Name </th> + <th> Username </th> + <th> Roll number </th> + <th> Questions answered </th> + <th> Total marks </th> + <th> Attempts </th> </tr> {% for paper in paper_list %} <tr> - <td> {{ paper.username }} </td> + <td> <a href="{{URL_ROOT}}/exam/user_data/{{paper.username}}">{{ paper.name }}</a> </td> + <td> <a href="{{URL_ROOT}}/exam/user_data/{{paper.username}}">{{ paper.username }}</a> </td> <td> {{ paper.rollno }} </td> <td> {{ paper.answered }} </td> <td> {{ paper.total }} </td> - + <td> {{ paper.attempts }} </td> </tr> {% endfor %} </table> -{% else %} +{% else %} {% if quiz_name %} <p> No answer papers so far. </p> + {% endif %} {% endif %} {% endblock content %} diff --git a/templates/exam/user_data.html b/templates/exam/user_data.html new file mode 100644 index 0000000..7560903 --- /dev/null +++ b/templates/exam/user_data.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block title %} Data for user {{ user_data.name }} {% endblock title %} + +{% block content %} + +<h1> Data for user {{ user_data.name }} </h1> + +<p> Name: {{ user_data.name }} </p> +<p> Username: {{ user_data.username }} </p> +<p> Roll number: {{ user_data.rollno }} </p> +<p> Email: {{ user_data.email }} </p> + +{% if user_data.papers %} + +{% for paper in user_data.papers %} + +<h2> Quiz: {{ paper.name }} </h2> + +<p> Answered questions: {{ paper.answered }} </p> +<p> Total attempts at questions: {{ paper.attempts }} </p> +<p> Total marks: {{ paper.total }} </p> + +{% if paper.answers %} +<h3> Answers </h3> +{% for question, answer in paper.answers.items %} +<h4> Question summary: {{ question }} </h4> +<pre> +{{ answer|safe }} +</pre> +{% endfor %} +{% endif %} {# if paper.answers #} + +{% endfor %} {# for paper in user_data.papers #} + +{% endif %} {# if user_data.papers #} + +{% endblock content %} |