* Pass marks can be set
* Multiple choice question type
* True/False question type
+* Essay question type
* Custom message displayed for those that pass or fail a quiz
* Custom permission (view_sittings) added, allowing users with that permission to view quiz results from users
+* A marking page which lists completed quizzes, can be filtered by quiz or user, and is used to mark essay questions
-from django.contrib import admin
-
-# Register your models here.
+# from django.contrib import admin
def answer_choice_to_string(self, guess):
return str(guess)
+ def __unicode__(self):
+ return unicode(self.content)
+
class Meta:
verbose_name = "Essay style question"
-from django.shortcuts import render
-
-# Create your views here.
+#from django.shortcuts import render
class EssayForm(forms.Form):
def __init__(self, question, *args, **kwargs):
super(EssayForm, self).__init__(*args, **kwargs)
- self.fields["answers"] = forms.CharField(widget=Textarea)
+ self.fields["answers"] = forms.CharField(
+ widget=Textarea(attrs={'style': 'width:100%'}))
self.save()
def add_to_score(self, points):
- self.current_score = self.get_current_score + int(points)
+ self.current_score += int(points)
self.save()
@property
Adds uid of incorrect question to the list.
The question object must be passed in.
"""
- if isinstance(question, Question) is False:
- return False
- self.incorrect_questions += str(question.id) + ","
+ if len(self.incorrect_questions) > 0:
+ self.incorrect_questions += ','
+ self.incorrect_questions += str(question.id) + ","
+ if self.complete:
+ self.add_to_score(-1)
self.save()
@property
"""
return [int(q) for q in self.incorrect_questions.split(',') if q]
+ def remove_incorrect_question(self, question):
+ current = self.get_incorrect_questions
+ current.remove(question.id)
+ self.incorrect_questions = ','.join(map(str, current))
+ self.add_to_score(1)
+ self.save()
+
@property
def check_if_passed(self):
if self.get_percent_correct >= self.quiz.pass_mark:
user_answers = json.loads(self.user_answers)
for question in self.quiz.question_set.all().select_subclasses():
output[question] = user_answers[unicode(question.id)]
-
return output
<th>Question</th>
<th>User answer</th>
<th></th>
+ <th></th>
</tr>
</thead>
-n
+
<tbody>
{% for question, user_name in questions.items %}
{% if question.id in incorrect %}
<p>incorrect</p>
{% else %}
- <p>correct</p>
+ <p>Correct</p>
{% endif %}
</td>
+ <td>
+ <form action="" method="get">
+ <input type=hidden name="id" value="{{ question.id }}">
+ <button type="submit">Toggle whether correct</button>
+ </form>
+ </td>
</tr>
{% endfor %}
from .views import anon_session_score
from multichoice.models import MCQuestion, Answer
from true_false.models import TF_Question
+from essay.models import Essay_Question
class TestCategory(TestCase):
self.sitting.add_incorrect_question(question3)
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.assertEqual(self.sitting.complete, False)
self.sitting.mark_quiz_complete()
self.assertEqual(self.sitting.complete, True)
+ self.assertEqual(self.sitting.current_score, 0)
+ self.sitting.add_incorrect_question(self.question2)
+ self.assertEqual(self.sitting.current_score, -1)
+
def test_add_user_answer(self):
guess = '123'
self.sitting.add_user_answer(self.question1, guess)
self.assertEqual('123', user_answers[self.question1])
self.assertEqual('456', user_answers[self.question2])
+ def test_remove_incorrect_answer(self):
+ self.sitting.add_incorrect_question(self.question1)
+ self.sitting.add_incorrect_question(self.question2)
+ self.sitting.remove_incorrect_question(self.question1)
+ self.assertEqual(self.sitting.incorrect_questions, '2')
+ self.assertEqual(self.sitting.current_score, 1)
+
'''
Tests relating to views
sitting2.save()
sitting1.add_user_answer(self.question1, '123')
- # sitting1.add_user_answer(self.question2, '456')
def test_paper_marking_list_view(self):
response = self.client.get('/marking/')
self.assertContains(response, 'squawk')
self.assertContains(response, 'incorrect')
+ def test_paper_marking_detail_toggle_correct(self):
+ question2 = Essay_Question.objects.create(id=3, content='scribble')
+ question2.quiz.add(self.quiz1)
+
+ sitting3 = Sitting.objects.new_sitting(self.student, self.quiz1)
+ sitting3.complete = True
+ sitting3.incorrect_questions = '1,2,3'
+ sitting3.add_user_answer(self.question1, '123')
+ sitting3.add_user_answer(question2, 'Blah blah blah')
+ sitting3.save()
+
+ self.client.login(username='yoda', password='use_d@_force')
+ response = self.client.get('/marking/3/')
+ self.assertContains(response, 'button')
+ self.assertNotContains(response, 'Correct')
+
+ response = self.client.get('/marking/3/', {'id': 3})
+ self.assertContains(response, 'Correct')
+
+ response = self.client.get('/marking/3/', {'id': 3})
+ self.assertNotContains(response, 'Correct')
+
class TestQuestionViewsAnon(TestCase):
urls = 'quiz.urls'
class QuizMarkingDetail(QuizMarkerMixin, DetailView):
model = Sitting
- def dispatch(self, request, *args, **kwargs):
- return super(QuizMarkingDetail, self)\
- .dispatch(request, *args, **kwargs)
+ def get_object(self, queryset=None):
+ sitting = super(QuizMarkingDetail, self).get_object()
+
+ q_to_toggle = self.request.GET.get('id')
+ if q_to_toggle:
+ q = Question.objects.get_subclass(id=int(q_to_toggle))
+ if int(q_to_toggle) in sitting.get_incorrect_questions:
+ sitting.remove_incorrect_question(q)
+ else:
+ sitting.add_incorrect_question(q)
+
+ return sitting
def get_context_data(self, **kwargs):
context = super(QuizMarkingDetail, self).get_context_data(**kwargs)