more fixes

This commit is contained in:
Ross
2021-01-18 14:00:37 +00:00
parent 542e559ed1
commit 558bd69ee5
5 changed files with 158 additions and 7 deletions
-2
View File
@@ -156,7 +156,6 @@ AnswerFormSet = inlineformset_factory(
can_delete=True,
extra=1,
max_num=10,
field_classes="testing",
)
AnswerUpdateFormSet = inlineformset_factory(
@@ -172,7 +171,6 @@ AnswerUpdateFormSet = inlineformset_factory(
can_delete=True,
extra=0,
max_num=10,
field_classes="testing",
)
+1 -1
View File
@@ -23,7 +23,7 @@ with open('/etc/secret_key') as f:
SECRET_KEY = f.read().strip()
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
DEBUG = True
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "161.35.163.87", "penracourses.org.uk"]
+14 -1
View File
@@ -1,5 +1,6 @@
from django.contrib import admin
from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, Note, RapidCreationDefault
from .models import Rapid, RapidImage, Examination, Site, Abnormality, Region, Note, RapidCreationDefault, Answer, Exam
#import tagulous.admin
from django.forms import ModelForm
@@ -10,10 +11,16 @@ from django.forms.widgets import RadioSelect
# Register your models here.
admin.site.register(Examination)
admin.site.register(Site)
admin.site.register(Exam)
admin.site.register(Abnormality)
admin.site.register(Region)
admin.site.register(Note)
admin.site.register(RapidCreationDefault)
admin.site.register(Answer)
class RapidAnswersInline(admin.TabularInline):
model = Answer
extra = 1
class RapidImageInline(admin.TabularInline):
@@ -23,6 +30,10 @@ class RapidImageInline(admin.TabularInline):
"image_tag",
]
class ExamInline(admin.TabularInline):
model = Rapid.exams.through
extra = 1
class RapidAdminForm(ModelForm):
class Meta:
@@ -52,6 +63,8 @@ class RapidAdmin(VersionAdmin):
inlines = [
RapidImageInline,
RapidAnswersInline,
ExamInline,
]
+32 -2
View File
@@ -1,10 +1,10 @@
from django.forms import ModelForm, ModelMultipleChoiceField, ModelChoiceField, ChoiceField
from django.forms import inlineformset_factory
from rapids.models import Abnormality, Examination, Note, Rapid, RapidCreationDefault, RapidImage, Region
from rapids.models import Abnormality, Examination, Note, Rapid, RapidCreationDefault, RapidImage, Region, Answer
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms.widgets import RadioSelect
from django.forms.widgets import RadioSelect, TextInput, Textarea
class ExaminationForm(ModelForm):
@@ -100,3 +100,33 @@ ImageFormSet = inlineformset_factory(Rapid,
extra=4,
max_num=10,
field_classes="testing")
AnswerFormSet = inlineformset_factory(
Rapid,
Answer,
fields=["answer", "status"],
widgets={
"answer": Textarea(
attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
)
},
exclude=[],
can_delete=True,
extra=1,
max_num=10,
)
AnswerUpdateFormSet = inlineformset_factory(
Rapid,
Answer,
fields=["answer", "status"],
widgets={
"answer": Textarea(
attrs={"required": "true", "minlength": 2, "maxlength": 500, "rows": 3}
)
},
exclude=[],
can_delete=True,
extra=0,
max_num=10,
)
+111 -1
View File
@@ -129,7 +129,7 @@ class Rapid(models.Model):
abnormality = models.ManyToManyField(
Abnormality,
blank=True,
help_text="The abnormality (laterality and region independent)",
help_text="The abnormality (laterality and region independent). Used for categorisation but does not affect the answer",
)
region = models.ManyToManyField(
Region,
@@ -310,3 +310,113 @@ class RapidCreationDefault(models.Model):
def get_absolute_url(self):
return reverse('rapids:rapid_create')
class Exam(models.Model):
name = models.CharField(max_length=200)
exam_questions = SortedManyToManyField(
Rapid, related_name="exams", blank="true"
)
active = models.BooleanField(
help_text="If an exam should be available", default=True
)
publish_results = models.BooleanField(
help_text="If an exams results should be available", default=True
)
recreate_json = models.BooleanField(
help_text="If the json cache needs updating", default=False
)
time_limit = models.IntegerField(
help_text="Exam time limit (in seconds)", default=5400
)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("rapids:exam_overview", kwargs={"pk": self.pk})
def get_exam_name(self):
return self.name
def get_json_url(self):
return reverse("rapids:exam_json", args=(self.pk,))
def get_question_index(self, question):
return list(self.exam_questions.all()).index(question)
class CidUserAnswer(models.Model):
"""User answers by candidate"""
question = models.ForeignKey(
Rapid, related_name="cid_user_answers", on_delete=models.CASCADE
)
answer = models.TextField(max_length=500, blank=True)
answer_compare = models.TextField(max_length=500, blank=True)
cid = models.BigIntegerField(blank=True, null=True, help_text="Candidate ID (limitied by BigIntegerField size)")
# 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.GetPrimaryAnswer(), self.answer
)
def save(self, *args, **kwargs):
self.clean()
return super(CidUserAnswer, self).save(*args, **kwargs)
def clean(self):
if self.answer:
self.answer = self.answer.strip()
s = self.answer.lower()
s = s.translate(str.maketrans('', '', string.punctuation))
self.answer_compare = s
# def get_compare_string(self):
# # strip here should be unneccasry (providing clean is now working)
# s = self.answer.lower().strip()
# s = s.translate(str.maketrans('', '', string.punctuation))
# return s
def get_answer_score(self):
q = self.question
ans = self.answer_compare
if (
q.answers.filter(
answer_compare__iexact=ans, status=Answer.MarkOptions.CORRECT
).first()
is not None
):
mark = 2
elif (
q.answers.filter(
answer_compare__iexact=ans, status=Answer.MarkOptions.HALF_MARK
).first()
is not None
):
mark = 1
elif q.answers.filter(
answer_compare__iexact=ans, status=Answer.MarkOptions.INCORRECT
).first():
mark = 0
else:
mark = "unmarked"
return mark