from django.db import models from django.utils import timezone from django.core.files.storage import FileSystemStorage from django.conf import settings image_storage = FileSystemStorage( # Physical file location ROOT location=u"{0}/anatomy/".format(settings.MEDIA_ROOT), # Url for file base_url=u"{0}anatomy/".format(settings.MEDIA_URL), ) def image_directory_path(instance, filename): # file will be uploaded to MEDIA_ROOT/anatomy/picture/ return u"picture/{0}".format(filename) class Examination(models.Model): examination = models.CharField(max_length=200) def __str__(self): return self.examination class BodyPart(models.Model): bodypart = models.CharField(max_length=200) def __str__(self): return self.bodypart class Structure(models.Model): bodypart = models.CharField(max_length=200) def __str__(self): return self.bodypart class Modality(models.Model): modality = models.CharField(max_length=200) def __str__(self): return self.modality class QuestionType(models.Model): text = models.CharField(max_length=400) def __str__(self): return self.text class AnatomyQuestion(models.Model): # author = models.ForeignKey('auth.User', on_delete=models.CASCADE) # image = models.ImageField() # feedback = models.TextField(null=True) question_type = models.ForeignKey(QuestionType, on_delete=models.SET_NULL, null=True) image = models.ImageField(upload_to=image_directory_path, storage=image_storage) description = models.CharField( max_length=400, help_text= "Short description of the image e.g. 'Sagittal CT Chest, Abdomen & Pelvis', will be displayed as the title." ) examination = models.ForeignKey(Examination, on_delete=models.SET_NULL, null=True, blank=True) modality = models.ForeignKey(Modality, on_delete=models.SET_NULL, null=True, help_text="Modality of the image") body_part = models.ForeignKey(BodyPart, on_delete=models.SET_NULL, null=True, blank=True) structure = models.ForeignKey(Structure, on_delete=models.SET_NULL, null=True, blank=True) created_date = models.DateTimeField(default=timezone.now) def __str__(self): # Get first answer a = self.answers.all().first() # Get associated exams e = self.exams.all().values_list("name", flat=True) exams = ", ".join(e) if a is None: return "({})".format(exams) else: return "{} ({}) [{}, {}]".format(a.answer, exams, self.modality, self.structure) def GetUnmarkedAnswersString(self): unmarked_answers = self.GetUnmarkedAnswers() if not unmarked_answers: return "No answers to mark" return "{} answer unmarked: {}".format(len(unmarked_answers), ", ".join(unmarked_answers)) def GetUnmarkedAnswers(self): user_answers = set([i.answer for i in self.user_answers.all()]) unmarked_answers = user_answers - self.GetMarkedAnswers() return unmarked_answers def GetMarkedAnswers(self): correct_answers = set([i.answer for i in self.answers.all()]) half_mark_answers = set( [i.answer for i in self.half_mark_answers.all()]) incorrect_answers = set( [i.answer for i in self.incorrect_answers.all()]) marked_answers = correct_answers | half_mark_answers | incorrect_answers return marked_answers class Answers(models.Model): question = models.ForeignKey(AnatomyQuestion, related_name="answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500) def __str__(self): return self.answer def clean(self): if self.answer: self.answer.strip() class HalfMarkAnswers(models.Model): question = models.ForeignKey(AnatomyQuestion, related_name="half_mark_answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500) def __str__(self): return self.answer def clean(self): if self.answer: self.answer.strip() class IncorrectAnswers(models.Model): question = models.ForeignKey(AnatomyQuestion, related_name="incorrect_answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500) def __str__(self): return self.answer def clean(self): if self.answer: self.answer.strip() class Exam(models.Model): name = models.CharField(max_length=200) exam_questions = models.ManyToManyField(AnatomyQuestion, related_name="exams") active = models.BooleanField(help_text="If an exam should be available", default=True) def __str__(self): return self.name class UserAnswer(models.Model): question = models.ForeignKey(AnatomyQuestion, related_name="user_answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500, blank=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL) cid = models.IntegerField(blank=True, null=True) # Each user answer is associated with a particular exam exam = models.ForeignKey(Exam, related_name="exam", on_delete=models.CASCADE, null=True) flagged = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) def __str__(self): try: exam = self.exam except (Exam.DoesNotExist, KeyError) as e: exam = "None" return "{}/{}/{}: {}".format(exam, self.cid, self.question.id, self.answer) def clean(self): if self.answer: self.answer.strip() class CidUserAnswer(models.Model): """User answers by candidate""" question = models.ForeignKey(AnatomyQuestion, related_name="cid_user_answers", on_delete=models.CASCADE) answer = models.CharField(max_length=500, blank=True) 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): try: exam = self.exam except (Exam.DoesNotExist, KeyError) as e: exam = "None" return "{}/{}/{}: {}".format(exam, self.cid, self.question.id, self.answer) def clean(self): if self.answer: self.answer.strip()