from django.db import models from django.utils import timezone from django.core.files.storage import FileSystemStorage from django.conf import settings from django.utils.html import format_html from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from sortedm2m.fields import SortedManyToManyField from generic.models import ExamBase import reversion class Category(models.Model): category = models.CharField(max_length=200) def __str__(self): return self.category class Question(models.Model): stem = models.TextField( blank=False, help_text="Stem of the question", ) answer_help_text = "Answer text" BEST_ANSWER_CHOICES = ( ('a', 'a_answer'), ('b', 'b_answer'), ('c', 'c_answer'), ('d', 'd_answer'), ('e', 'e_answer'), ) # I doubt this is the best way to structure the model # (but it should work) a_answer = models.TextField( help_text=answer_help_text ) a_feedback = models.TextField( blank=True, help_text="Feedback for answer", ) b_answer = models.TextField( help_text=answer_help_text ) b_feedback = models.TextField( blank=True, help_text="Feedback for answer", ) c_answer = models.TextField( help_text=answer_help_text ) c_feedback = models.TextField( blank=True, help_text="Feedback for answer", ) d_answer = models.TextField( help_text=answer_help_text ) d_feedback = models.TextField( blank=True, help_text="Feedback for answer", ) e_answer = models.TextField( help_text=answer_help_text ) e_feedback = models.TextField( blank=True, help_text="Feedback for answer", ) feedback = models.TextField( blank=True, help_text="General question feedback", ) best_answer = models.CharField(max_length=20, choices=BEST_ANSWER_CHOICES, help_text="The correct answer") created_date = models.DateTimeField(default=timezone.now) author = models.ManyToManyField( settings.AUTH_USER_MODEL, blank=True, help_text="Author(s) of question", related_name="sbas_authored_questions", ) category = models.ForeignKey( Category, on_delete=models.SET_NULL, null=True, blank=True ) def __str__(self): return self.stem def clean(self): if self.a_answer: self.a_answer = self.a_answer.strip() if self.b_answer: self.b_answer = self.b_answer.strip() if self.c_answer: self.c_answer = self.c_answer.strip() if self.d_answer: self.d_answer = self.d_answer.strip() if self.e_answer: self.e_answer = self.e_answer.strip() def get_absolute_url(self): return reverse("sbas:question_detail", kwargs={"pk": self.pk}) def get_answers(self): return (self.a_answer, self.b_answer, self.c_answer, self.d_answer, self.e_answer) def get_correct_answer(self): if self.best_answer == "a": return self.a_answer if self.best_answer == "b": return self.b_answer if self.best_answer == "c": return self.c_answer if self.best_answer == "d": return self.d_answer if self.best_answer == "e": return self.e_answer def get_correct_answer_stripped(self): return self.get_correct_answer().replace("

","",1).replace("

","",1) def get_stem_stripped(self): return self.stem.replace("

","",1).replace("

","",1) @reversion.register class Exam(ExamBase): app_name = "sbas" exam_questions = SortedManyToManyField( Question, related_name="exams", blank="true" ) time_limit = models.IntegerField( help_text="Exam time limit (in seconds)", blank=True, null=True, ) recreate_json = None author = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, help_text='Author of exam', related_name="sba_exam_author") @reversion.register class CidUserAnswer(models.Model): """User answers by candidate""" question = models.ForeignKey( Question, related_name="cid_user_answers", on_delete=models.CASCADE ) answer = models.CharField(max_length=20, choices=Question.BEST_ANSWER_CHOICES, help_text="The correct answer") cid = models.IntegerField(blank=True, null=True) # Each user answer is associated with a particular exam exam = models.ForeignKey( Exam, related_name="cid_user_answers", on_delete=models.CASCADE, null=True ) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) def __str__(self): return "{}/{}/{}".format(self.cid, self.exam, self.question.pk) def get_answer(self): return self.answer def get_correct(self): return self.answer == self.question.best_answer def get_score(self): if self.get_correct(): return 1 return 0