Files
penracourses/anatomy/models.py
T
2020-11-26 21:35:06 +00:00

287 lines
9.0 KiB
Python

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 _
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/<filename>
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):
structure = models.CharField(max_length=200)
def __str__(self):
return self.structure
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)
open_access = models.BooleanField(help_text="If an question should be freely available to browse",
default=True)
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 GetPrimaryAnswer(self):
return self.answers.all().first().answer
def GetExams(self):
e = self.exams.all().values_list("name", flat=True)
exams = ", ".join(e)
return exams
def GetUnmarkedAnswersString(self):
unmarked_answers = self.GetUnmarkedAnswers()
if not unmarked_answers:
return "No answers to mark"
return format_html(
"<span class='warn'>{} answer unmarked:</span> {}".format(
len(unmarked_answers), ", ".join(unmarked_answers)))
def GetUnmarkedAnswers(self):
user_answers = set(
[i.get_compare_string() for i in self.cid_user_answers.all()])
unmarked_answers = user_answers - self.GetMarkedAnswers()
return unmarked_answers
def GetMarkedAnswers(self):
return set([i.get_compare_string() for i in self.answers.all() if i.status != i.MarkOptions.UNMARKED])
correct_answers = set([i.answer.lower() for i in self.answers.all()])
half_mark_answers = set(
[i.answer.lower() for i in self.half_mark_answers.all()])
incorrect_answers = set(
[i.answer.lower() for i in self.incorrect_answers.all()])
marked_answers = correct_answers | half_mark_answers | incorrect_answers
return marked_answers
class Answer(models.Model):
question = models.ForeignKey(AnatomyQuestion,
related_name="answers",
on_delete=models.CASCADE)
answer = models.CharField(max_length=500)
class MarkOptions(models.TextChoices):
UNMARKED = '', _('Unmarked')
INCORRECT = '0', _('Incorrect')
HALF_MARK = '1', _('Half mark')
CORRECT = '2', _('Correct')
status = models.CharField(max_length=1, choices=MarkOptions.choices, default=MarkOptions.UNMARKED)
def __str__(self):
return self.answer
def clean(self):
if self.answer:
self.answer.strip()
def get_compare_string(self):
return self.answer.lower()
#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", blank="true")
active = models.BooleanField(help_text="If an exam should be available",
default=True)
def __str__(self):
return self.name
def get_exam_name(self):
return self.name
def get_json_url(self):
return reverse('anatomy:exam_json', args=(self.pk, ))
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()
def get_compare_string(self):
return self.answer.lower()