From: Tom Walker Date: Sun, 27 Jul 2014 13:15:58 +0000 (+0100) Subject: finalised essay question type, added it to admin and readme, adjusted X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=7700b480d94302a3345e9a2aa29cf9274007b6be;p=django_quiz.git finalised essay question type, added it to admin and readme, adjusted sitting detail view to allow a marker to decide whether a question is correct, added supporting methods to the sitting model --- diff --git a/README.md b/README.md index 4ebb78d..45e131b 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,10 @@ Features of each quiz: * 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 diff --git a/essay/admin.py b/essay/admin.py index 8c38f3f..d3c1eff 100644 --- a/essay/admin.py +++ b/essay/admin.py @@ -1,3 +1 @@ -from django.contrib import admin - -# Register your models here. +# from django.contrib import admin diff --git a/essay/models.py b/essay/models.py index 96a6b43..9f0c5d1 100644 --- a/essay/models.py +++ b/essay/models.py @@ -15,5 +15,8 @@ class Essay_Question(Question): def answer_choice_to_string(self, guess): return str(guess) + def __unicode__(self): + return unicode(self.content) + class Meta: verbose_name = "Essay style question" diff --git a/essay/views.py b/essay/views.py index 91ea44a..497e342 100644 --- a/essay/views.py +++ b/essay/views.py @@ -1,3 +1 @@ -from django.shortcuts import render - -# Create your views here. +#from django.shortcuts import render diff --git a/quiz/forms.py b/quiz/forms.py index bb74388..c7ddf69 100644 --- a/quiz/forms.py +++ b/quiz/forms.py @@ -13,4 +13,5 @@ class QuestionForm(forms.Form): 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%'})) diff --git a/quiz/models.py b/quiz/models.py index 97d64f0..60ed009 100644 --- a/quiz/models.py +++ b/quiz/models.py @@ -358,7 +358,7 @@ class Sitting(models.Model): 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 @@ -391,9 +391,11 @@ class Sitting(models.Model): 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 @@ -404,6 +406,13 @@ class Sitting(models.Model): """ 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: @@ -429,7 +438,6 @@ class Sitting(models.Model): 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 diff --git a/quiz/templates/quiz/sitting_detail.html b/quiz/templates/quiz/sitting_detail.html index a685b9a..254dfb5 100644 --- a/quiz/templates/quiz/sitting_detail.html +++ b/quiz/templates/quiz/sitting_detail.html @@ -18,9 +18,10 @@ Result of {{ sitting.quiz.title }} for {{ sitting.user }} Question User answer + -n + {% for question, user_name in questions.items %} @@ -31,9 +32,15 @@ n {% if question.id in incorrect %}

incorrect

{% else %} -

correct

+

Correct

{% endif %} + +
+ + +
+ {% endfor %} diff --git a/quiz/tests.py b/quiz/tests.py index 0e4a2f7..85b7340 100644 --- a/quiz/tests.py +++ b/quiz/tests.py @@ -13,6 +13,7 @@ from .models import Category, Quiz, Progress, Sitting 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): @@ -246,14 +247,14 @@ class TestSitting(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) @@ -268,6 +269,13 @@ class TestSitting(TestCase): 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 @@ -400,7 +408,6 @@ class TestQuestionMarking(TestCase): 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/') @@ -457,6 +464,28 @@ class TestQuestionMarking(TestCase): 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' diff --git a/quiz/views.py b/quiz/views.py index 29b25a1..9889fb7 100644 --- a/quiz/views.py +++ b/quiz/views.py @@ -95,9 +95,18 @@ class QuizMarkingList(QuizMarkerMixin, ListView): 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)