]> git.parisson.com Git - django_quiz.git/commitdiff
added the option to allow a quiz to be only sat once by registered users, not at...
authorTom Walker <tomwalker0472@gmail.com>
Mon, 30 Jun 2014 16:45:33 +0000 (17:45 +0100)
committerTom Walker <tomwalker0472@gmail.com>
Mon, 30 Jun 2014 16:45:33 +0000 (17:45 +0100)
quiz/models.py
quiz/templates/result.html
quiz/templates/single_complete.html [new file with mode: 0644]
quiz/tests.py
quiz/views.py

index 8d83359788877b9905b738275c3446def8501d30..517cc2335d4bfd4f7e4cc8a4bf4c2762793ef21f 100644 (file)
@@ -14,7 +14,6 @@ from model_utils.managers import InheritanceManager
 If you want to prepopulate the category choices then here is an example.
 Uncomment 'choices' in the category model.
 """
-
 CATEGORY_CHOICES = ( ('Endocrinology', 'Endocrinology'),
                      ('Dermatology', 'Dermatology'),
                      ('Cellular Biology', 'Cellular Biology'),
@@ -73,12 +72,12 @@ class Quiz(models.Model):
                              blank = False,)
 
     description = models.TextField(blank = True,
-                                   help_text = "a description of the quiz",)
+                                   help_text = ("a description of the quiz"),)
 
     url = models.CharField(max_length = 60,
                            blank = False,
-                           help_text = "an SEO friendly url",
-                           verbose_name = 'SEO friendly url',)
+                           help_text = ("a user friendly url"),
+                           verbose_name = ('user friendly url'),)
 
     category = models.ForeignKey(Category,
                                  null = True,
@@ -86,19 +85,30 @@ class Quiz(models.Model):
 
     random_order = models.BooleanField(blank = False,
                                        default = False,
-                                       help_text = "Display the questions in a \
-                                       random order or as they are set?",)
+                                       help_text = ("Display the questions in \
+                                                    a random order or as they \
+                                                    are set?"),)
 
     answers_at_end = models.BooleanField(blank = False,
                                          default = False,
-                                         help_text = "Correct answer is NOT \
-                                         shown after question. Answers \
-                                         displayed at end",)
+                                         help_text = ("Correct answer is NOT \
+                                                      shown after question. \
+                                                      Answers displayed at \
+                                                      the end"),)
 
     exam_paper = models.BooleanField(blank = False,
                                      default = False,
-                                     help_text = "If yes, the result of each \
-                                     attempt by a user will be stored",)
+                                     help_text = ("If yes, the result of each \
+                                                  attempt by a user will be \
+                                                  stored"),)
+
+    single_attempt = models.BooleanField(blank = False,
+                                         default = False,
+                                         help_text = ("If yes, only one \
+                                                       attempt by a user will \
+                                                       be permitted. Non \
+                                                       users cannot sit \
+                                                       this exam."),)
 
 
     def save(self, force_insert = False, force_update = False, *args, **kwargs):
@@ -107,6 +117,9 @@ class Quiz(models.Model):
         self.url = ''.join(letter for letter in self.url if
                            letter.isalnum() or letter == '-')
 
+        if self.single_attempt == True:
+            self.exam_paper = True
+
         super(Quiz, self).save(force_insert, force_update, *args, **kwargs)
 
 
@@ -140,13 +153,10 @@ class Progress(models.Model):
     Data stored in csv using the format:
         category, score, possible, category, score, possible, ...
     """
-
     user = models.OneToOneField('auth.User')  #  one user per progress class
 
-    #  The god awful csv. Always end with a comma
     score = models.CommaSeparatedIntegerField(max_length = 1024)
 
-
     objects = ProgressManager()
 
     class Meta:
@@ -164,7 +174,6 @@ class Progress(models.Model):
 
         The dict will have one key for every category that you have defined
         """
-
         categories = Category.objects.all()
         score_before = self.score
         output = {}
index c24c6d5b229d98f2db581b7a2fd658b0fb3be9f2..0da8bdea06a92d0c60931061e2ac95a0370579c8 100644 (file)
@@ -23,7 +23,7 @@
 
 {% endif %}
 
-{% if score %}
+{% if score or max_score %}
 
        <div>
                <h2>Exam results</h2>
diff --git a/quiz/templates/single_complete.html b/quiz/templates/single_complete.html
new file mode 100644 (file)
index 0000000..2c5e50c
--- /dev/null
@@ -0,0 +1,20 @@
+{% extends "base.html" %}
+
+{% load quiz_tags %}
+
+{% block title %} {{ quiz.title }} {% endblock %}
+{% block description %} {{ quiz.title }} - {{ quiz.description }} {% endblock %}
+
+{% block content %}
+
+<div class="container">
+
+{% if user.is_authenticated %}
+  <p>You have already sat this exam and only one sitting is permitted.</p>
+{% else %}
+  <p>This exam is only accessible to signed in users.</p>
+{% endif %}
+
+</div>
+
+{% endblock %}
index 41211b4edba436543ee52934e0e5ff9389ca01a6..8bad8a5abb8a880c7b48ed3fad5c6cc1757e33a5 100644 (file)
@@ -68,6 +68,12 @@ class TestQuiz(TestCase):
         self.assertEqual(q5.answers_at_end, False)
         self.assertEqual(q5.exam_paper, True)
 
+    def test_quiz_single_attempt(self):
+        self.quiz1.single_attempt = True
+        self.quiz1.save()
+
+        self.assertEqual(self.quiz1.exam_paper, True)
+
 
 class TestProgress(TestCase):
     def setUp(self):
@@ -203,6 +209,7 @@ class TestSitting(TestCase):
         self.sitting.mark_quiz_complete()
         self.assertEqual(self.sitting.complete, True)
 
+
 '''
 Tests relating to views
 '''
@@ -394,6 +401,16 @@ class TestQuestionViewsAnon(TestCase):
         self.assertEqual(self.client.session['session_score'], 1)
         self.assertEqual(self.client.session['session_score_possible'], 3)
 
+    def test_anon_cannot_sit_single_attempt(self):
+        self.quiz1.single_attempt = True
+        self.quiz1.save()
+        response = self.client.get('/q/tq1/')
+
+        self.assertContains(response, 'accessible')
+        self.assertTemplateUsed('single_complete.html')
+
+
+
 class TestQuestionViewsUser(TestCase):
 
     def setUp(self):
@@ -526,8 +543,8 @@ class TestQuestionViewsUser(TestCase):
         self.assertEqual(response.context['previous'], {})
 
         response = self.client.get('/q/tq2/',
-                                   {'guess': 456,
-                                    'question_id': 2})
+                                   {'guess': 'T',
+                                    'question_id': 3})
 
         self.assertEqual(response.context['score'], 1)
         self.assertEqual(response.context['max_score'], 2)
@@ -547,6 +564,23 @@ class TestQuestionViewsUser(TestCase):
         # test that exam result can be recalled later
         self.assertIn(sitting, progress.show_exams())
 
+    def test_user_cannot_sit_single_attempt(self):
+        self.quiz2.single_attempt = True
+        self.quiz2.save()
+        self.client.login(username='jacob', password='top_secret')
+        response = self.client.get('/q/tq2/',
+                                   {'guess': '123',
+                                    'question_id': 1})
+        response = self.client.get('/q/tq2/',
+                                   {'guess': 'T',
+                                    'question_id': 3})
+
+        # quiz complete, trying it again
+        response = self.client.get('/q/tq2/')
+
+        self.assertContains(response, 'only one sitting is permitted.')
+        self.assertTemplateUsed('single_complete.html')
+
 class TestTemplateTags(TestCase):
 
     def setUp(self):
@@ -621,8 +655,8 @@ class TestTemplateTags(TestCase):
 
     def test_correct_answer_all_anon(self):
         template = Template( '{% load quiz_tags %}' +
-                             '{% correct_answer_for_all_with_users_incorrect ' +
-                             'question  incorrect_questions %}')
+                             '{% correct_answer_for_all_with_users_incorrect' +
+                             ' question  incorrect_questions %}')
 
         context = Context({'question': self.question1,})
 
index c288f0249c11c4830d47e0ecd500aebf811fc387..45a98f669c7ea6e046f19e58f28127fd5bc9d30f 100644 (file)
@@ -33,6 +33,19 @@ def quiz_take(request, quiz_name):
     quiz = Quiz.objects.get(url = quiz_name.lower())
 
     if request.user.is_authenticated() == True:
+
+        if quiz.single_attempt == True:
+            try:
+                single = Sitting.objects.get(user = request.user,
+                                            quiz = quiz,
+                                            complete = True)
+            except Sitting.DoesNotExist:
+                pass
+            except Sitting.MultipleObjectsReturned:
+                return render(request, 'single_complete.html')
+            else:
+                return render(request, 'single_complete.html')
+
         try:
             previous_sitting = Sitting.objects.get(user = request.user,
                                                    quiz = quiz,
@@ -54,6 +67,8 @@ def quiz_take(request, quiz_name):
 
 
     else:  #  anon user
+        if quiz.single_attempt == True:
+            return render(request, 'single_complete.html')
         quiz_id = str(quiz.id)
         q_list = quiz_id + "_q_list"