]> git.parisson.com Git - django_quiz.git/commitdiff
added a new view which lists all completed exams, to allow an admin to view results
authorTom Walker <tomwalker0472@gmail.com>
Mon, 21 Jul 2014 21:12:40 +0000 (22:12 +0100)
committerTom Walker <tomwalker0472@gmail.com>
Mon, 21 Jul 2014 21:12:40 +0000 (22:12 +0100)
README.md
quiz/models.py
quiz/templates/quiz/sitting_detail.html [new file with mode: 0644]
quiz/templates/quiz/sitting_list.html [new file with mode: 0644]
quiz/templatetags/quiz_tags.py
quiz/tests.py
quiz/urls.py
quiz/views.py

index 6d3e5250d213fd827115b877bdb21749954e0772..34e9d3ade17dc909973cc929381d7a383e714197 100644 (file)
--- a/README.md
+++ b/README.md
@@ -23,8 +23,11 @@ Features of each quiz:
 * Questions can be given a category
 * Success rate for each category can be monitored on a progress page
 * Explanation for each question result can be given
+* Pass marks can be set
 * Multiple choice question type
 * True/False question type
+* Custom message displayed for those that pass or fail a quiz
+
 
 
 ![Result page](http://i.imgur.com/UJtRZxo.png "Result picture hosted by Imgur")
index 79f4b5f3f584e0b369eb71d33bc8908bcdae303c..c0b69138e1f5fcbd4c0cd8af3bb3640951d2fbe9 100644 (file)
@@ -386,11 +386,13 @@ class Sitting(models.Model):
         self.incorrect_questions += str(question.id) + ","
         self.save()
 
+    @property
     def get_incorrect_questions(self):
         """
-        Returns a list of non empty strings
+        Returns a list of non empty integers, representing the pk of
+        questions
         """
-        return filter(None, self.incorrect_questions.split(','))
+        return [int(q) for q in self.incorrect_questions.split(',') if q]
 
     @property
     def check_if_passed(self):
diff --git a/quiz/templates/quiz/sitting_detail.html b/quiz/templates/quiz/sitting_detail.html
new file mode 100644 (file)
index 0000000..65e8fc7
--- /dev/null
@@ -0,0 +1,42 @@
+{% extends 'base.html' %}
+{% block title %}
+Result of {{ sitting.quiz.title }} for {{ sitting.user }}
+{% endblock %}
+
+{% block content %}
+<h2>Quiz title: {{ sitting.quiz.title }}</h2>
+<h3>Category: {{ sitting.quiz.category }}</h3>
+<p>{{ sitting.quiz.description }}</p>
+<hr>
+<p>User: {{ sitting.user }}</p>
+<p>Score: {{ sitting.get_percent_correct }}%</p>
+
+<table class="table table-bordered table-striped">
+
+  <thead>
+       <tr>
+         <th>Question</th>
+         <th></th>
+       </tr>
+  </thead>
+
+  <tbody>
+{% for question in questions %}
+
+       <tr>
+         <td>{{ question.content }}</td>
+         <td>
+               {% if question.id in incorrect %}
+                 <p>incorrect</p>
+               {% else %}
+                 <p>correct</p>
+               {% endif %}
+         </td>
+       </tr>
+
+{% endfor %}
+
+  </tbody>
+
+</table>
+{% endblock %}
diff --git a/quiz/templates/quiz/sitting_list.html b/quiz/templates/quiz/sitting_list.html
new file mode 100644 (file)
index 0000000..8c01436
--- /dev/null
@@ -0,0 +1,41 @@
+{% extends 'base.html' %}
+{% block title %}All Quizzes{% endblock %}
+
+{% block content %}
+<h2>List of complete exams</h2>
+    {% if sitting_list %}
+
+               <table class="table table-bordered table-striped">
+
+                 <thead>
+                       <tr>
+                         <th>User</th>
+                         <th>Quiz</th>
+                         <th>Score (%)</th>
+                         <th></th>
+                       </tr>
+                 </thead>
+
+                 <tbody>
+
+        {% for sitting in sitting_list %}
+
+                       <tr>
+                         <td>{{ sitting.user }}</td>
+                         <td>{{ sitting.quiz }}</td>
+                         <td>{{ sitting.get_current_score }}</td>
+                         <td>
+                               <a href="{% url 'quiz_marking_detail' pk=sitting.id %}">
+                                 View details
+                               </a>
+                       </tr>
+
+        {% endfor %}
+
+                 </tbody>
+
+               </table>
+    {% else %}
+        <p>There are no complete quizzes.</p>
+    {% endif %}
+{% endblock %}
index e0715c4e7b246d9b31255f1992f98e2d78755b03..5f70026a13beab13ea5901e198f545ee65cb6978 100644 (file)
@@ -10,8 +10,8 @@ def correct_answer_for_all(context, question):
     if the answer is incorrect, informs the user
     """
     answers = question.get_answers()
-    incorrect_list = context.get('incorrect_questions', '')
-    if str(question.id) in incorrect_list:
+    incorrect_list = context.get('incorrect_questions', [])
+    if question.id in incorrect_list:
         user_was_incorrect = True
     else:
         user_was_incorrect = False
index a9a0d3f636b0a120cde1ab1ed4207d948f6405e3..1ddb2fa2f6a3a1255f58be94ccd38ad85a18ecc7 100644 (file)
@@ -226,19 +226,19 @@ class TestSitting(TestCase):
         self.assertEqual(self.sitting.result_message, 'Well done')
 
     def test_incorrect_and_complete(self):
-        self.assertEqual(self.sitting.get_incorrect_questions(), [])
+        self.assertEqual(self.sitting.get_incorrect_questions, [])
 
         self.sitting.add_incorrect_question(self.question1)
-        self.assertIn('1', self.sitting.get_incorrect_questions())
+        self.assertIn(1, self.sitting.get_incorrect_questions)
 
         question3 = TF_Question.objects.create(id=3,
                                                content='oink')
         self.sitting.add_incorrect_question(question3)
-        self.assertIn('3', self.sitting.get_incorrect_questions())
+        self.assertIn(3, self.sitting.get_incorrect_questions)
 
         f_test = self.sitting.add_incorrect_question(self.quiz1)
         self.assertEqual(f_test, False)
-        self.assertNotIn('test', self.sitting.get_incorrect_questions())
+        self.assertNotIn('test', self.sitting.get_incorrect_questions)
 
         self.assertEqual(self.sitting.complete, False)
         self.sitting.mark_quiz_complete()
@@ -334,6 +334,36 @@ class TestNonQuestionViews(TestCase):
         score, possible = anon_session_score(request.session)
         self.assertEqual((score, possible), (0.5, 2))
 
+    def test_paper_marking_view(self):
+        student = User.objects.create_user(username='luke',
+                                           email='luke@rebels.com',
+                                           password='top_secret')
+        teacher = User.objects.create_user(username='yoda',
+                                           email='yoda@jedis.com',
+                                           password='use_d@_force')
+        question1 = MCQuestion.objects.create(id=1, content='squawk')
+        question1.quiz.add(self.quiz1)
+        sitting1 = Sitting.objects.new_sitting(student, self.quiz1)
+        sitting2 = Sitting.objects.new_sitting(student, self.quiz2)
+        sitting1.complete = True
+        sitting1.incorrect_questions = '1'
+        sitting1.save()
+        sitting2.complete = True
+        sitting2.save()
+
+        response = self.client.get('/q/marking/')
+        self.assertRedirects(response, 'accounts/login/?next=/q/marking/',
+                             status_code=302, target_status_code=404 or 200)
+
+        self.client.login(username='yoda', password='use_d@_force')
+        response = self.client.get('/q/marking/')
+        self.assertContains(response, 'test quiz 1')
+
+        response = self.client.get('/q/marking/1/')
+        self.assertContains(response, 'test quiz 1')
+        self.assertContains(response, 'squawk')
+        self.assertContains(response, 'incorrect')
+
 
 class TestQuestionViewsAnon(TestCase):
 
@@ -678,7 +708,7 @@ class TestTemplateTags(TestCase):
                             '{% correct_answer_for_all question %}')
 
         context = Context({'question': self.question1,
-                           'incorrect_questions': '1,'})
+                           'incorrect_questions': [1]})
 
         self.assertTemplateUsed('correct_answer.html')
         self.assertIn('bing', template.render(context))
index ba1557907cbcd371431ee833b0e064215615fe36..db884ffe965435e82eb3bbce4cbab9398306e80b 100644 (file)
@@ -1,7 +1,8 @@
 from django.conf.urls import patterns, url
 
 from .views import QuizListView, CategoriesListView,\
-    ViewQuizListByCategory, QuizUserProgressView, QuizDetailView, QuizTake
+    ViewQuizListByCategory, QuizUserProgressView, QuizMarkingList,\
+    QuizMarkingDetail, QuizDetailView, QuizTake
 
 
 urlpatterns = patterns('',
@@ -22,6 +23,14 @@ urlpatterns = patterns('',
                            view=QuizUserProgressView.as_view(),
                            name='quiz_progress'),
 
+                       url(regex=r'^marking/$',
+                           view=QuizMarkingList.as_view(),
+                           name='quiz_marking'),
+
+                       url(regex=r'^marking/(?P<pk>[\d.]+)/$',
+                           view=QuizMarkingDetail.as_view(),
+                           name='quiz_marking_detail'),
+
                        #  passes variable 'quiz_name' to quiz_take view
                        url(regex=r'^(?P<slug>[\w-]+)/$',
                            view=QuizDetailView.as_view(),
index ad04ed38b01128108ef39449f3bc98eb1f5d4034..619862cfe28fe322d67d7e29c7b1c48b6bff5f26 100644 (file)
@@ -63,6 +63,33 @@ class QuizUserProgressView(TemplateView):
         return context
 
 
+class QuizMarkingList(ListView):
+    model = Sitting
+
+    @method_decorator(login_required)
+    def dispatch(self, request, *args, **kwargs):
+        return super(QuizMarkingList, self).dispatch(request, *args, **kwargs)
+
+    def get_queryset(self):
+        queryset = super(QuizMarkingList, self).get_queryset()
+        return queryset.filter(complete=True)
+
+
+class QuizMarkingDetail(DetailView):
+    model = Sitting
+
+    @method_decorator(login_required)
+    def dispatch(self, request, *args, **kwargs):
+        return super(QuizMarkingDetail, self)\
+            .dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        context = super(QuizMarkingDetail, self).get_context_data(**kwargs)
+        context['questions'] = context['object'].quiz.question_set.all()
+        context['incorrect'] = context['object'].get_incorrect_questions
+        return context
+
+
 class QuizTake(FormView):
     form_class = QuestionForm
     template_name = 'question.html'
@@ -164,7 +191,7 @@ def form_valid_user(self, form):
 
 def final_result_user(request, sitting, quiz, previous):
     score = sitting.get_current_score
-    incorrect = sitting.get_incorrect_questions()
+    incorrect = sitting.get_incorrect_questions
     max_score = quiz.get_max_score
     percent = sitting.get_percent_correct