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'),
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,
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):
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)
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:
The dict will have one key for every category that you have defined
"""
-
categories = Category.objects.all()
score_before = self.score
output = {}
{% endif %}
-{% if score %}
+{% if score or max_score %}
<div>
<h2>Exam results</h2>
--- /dev/null
+{% 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 %}
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):
self.sitting.mark_quiz_complete()
self.assertEqual(self.sitting.complete, True)
+
'''
Tests relating to views
'''
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):
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)
# 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):
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,})
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,
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"