Merge branch 'master' of ssh://git.xkjq.uk:30001/ross/rad

This commit is contained in:
Ross
2021-03-18 23:08:04 +00:00
9 changed files with 197 additions and 42 deletions
@@ -0,0 +1,18 @@
# Generated by Django 3.1.3 on 2021-03-09 15:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('anatomy', '0034_auto_20210215_1200'),
]
operations = [
migrations.AddField(
model_name='exam',
name='json_creation_time',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]
+2
View File
@@ -64,6 +64,8 @@ class ExamBase(models.Model):
help_text="If the json cache needs updating", default=False help_text="If the json cache needs updating", default=False
) )
json_creation_time = models.DateTimeField(blank=True, default=None, null=True)
#time_limit = models.IntegerField( #time_limit = models.IntegerField(
# help_text="Exam time limit (in seconds). Default is 2100 secondse (35 minutes)", # help_text="Exam time limit (in seconds). Default is 2100 secondse (35 minutes)",
# default=2100, # default=2100,
+45 -11
View File
@@ -32,6 +32,10 @@ from anatomy.models import AnatomyQuestion as AnatomyQuestion
from anatomy.models import Exam as AnatomyExam from anatomy.models import Exam as AnatomyExam
from django.db.models import Case, When from django.db.models import Case, When
from django.conf import settings
from datetime import datetime
import os
# Create your views here. # Create your views here.
@@ -177,6 +181,8 @@ class ExamViews(View, LoginRequiredMixin):
exam.recreate_json = True exam.recreate_json = True
exam.save() exam.save()
exam.get_exam_json()
return redirect("{}:exam_overview".format(self.app_name), pk=pk) return redirect("{}:exam_overview".format(self.app_name), pk=pk)
@method_decorator(login_required) @method_decorator(login_required)
@@ -315,13 +321,25 @@ class ExamViews(View, LoginRequiredMixin):
for exam in exams: for exam in exams:
if exam.active: if exam.active:
active_exams["exams"].append( if exam.json_creation_time:
{ creation_time = exam.json_creation_time.isoformat()
else:
creation_time = "None"
obj = {
"name": exam.get_exam_name(), "name": exam.get_exam_name(),
"url": request.build_absolute_uri(exam.get_json_url()), "url": request.build_absolute_uri(exam.get_json_url()),
"type": self.question_type, "type": self.question_type,
"eid": "{}/{}".format(self.question_type, exam.pk),
"json_creation_time": creation_time
} }
)
if self.question_type == "long":
h = {}
for question in exam.exam_questions.all():
h[question.pk] = question.json_creation_time.isoformat()
obj["multi_question_json"] = h
active_exams["exams"].append( obj )
if json == False: if json == False:
return active_exams["exams"] return active_exams["exams"]
@@ -356,24 +374,37 @@ class ExamViews(View, LoginRequiredMixin):
if not exam.active: if not exam.active:
raise Http404("No available exam") raise Http404("No available exam")
exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk))
if exam_json_cache is not None and not exam.recreate_json: #exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk))
exam_json_cache["cached"] = True
path= "{0}{1}/exam/{2}.json".format(settings.MEDIA_ROOT, self.app_name, pk)
url= "{0}{1}/exam/{2}.json".format(settings.MEDIA_URL, self.app_name, pk)
if os.path.isfile(path) and not exam.recreate_json:
#exam_json_cache["cached"] = True
return redirect(url)
return JsonResponse(exam_json_cache) return JsonResponse(exam_json_cache)
exam_json = exam.get_exam_json() time = datetime.now()
with open(path, "w+") as f:
exam_json = exam.get_exam_json()
exam_json["generated"] = time.isoformat()
f.write(json.dumps(exam_json))
exam.recreate_json = False exam.recreate_json = False
exam.json_creation_time = time
exam.save() exam.save()
# We also try to clear the cache of any associated questions (longs) # We also try to clear the cache of any associated questions (longs)
# see exam_question_json # see exam_question_json
n = exam.exam_questions.count() #n = exam.exam_questions.count()
question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)] #question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)]
cache.delete_many(question_keys) #cache.delete_many(question_keys)
cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600) #cache.set("{}_exam_json_{}".format(self.app_name, pk), exam_json, 3600)
return JsonResponse(exam_json) return JsonResponse(exam_json)
@@ -384,6 +415,9 @@ class ExamViews(View, LoginRequiredMixin):
if not exam.active: if not exam.active:
raise Http404("No available exam") raise Http404("No available exam")
return redirect("{}:question_json".format(self.app_name), pk=sk)
redirect()
question_json_cache = cache.get("{}_question_json_{}".format(self.app_name, sk)) question_json_cache = cache.get("{}_question_json_{}".format(self.app_name, sk))
if question_json_cache is not None and not question.recreate_json: if question_json_cache is not None and not question.recreate_json:
@@ -0,0 +1,23 @@
# Generated by Django 3.1.3 on 2021-03-09 15:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('longs', '0030_long_recreate_json'),
]
operations = [
migrations.AddField(
model_name='exam',
name='json_creation_time',
field=models.DateTimeField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name='long',
name='json_creation_time',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]
+60 -24
View File
@@ -1,3 +1,4 @@
import json
from django.db.models.fields.files import ImageField from django.db.models.fields.files import ImageField
from django.db.models.fields.related import ForeignKey from django.db.models.fields.related import ForeignKey
from django.db import models from django.db import models
@@ -34,6 +35,7 @@ from easy_thumbnails.files import get_thumbnailer
from easy_thumbnails.exceptions import InvalidImageFormatError from easy_thumbnails.exceptions import InvalidImageFormatError
import pydicom import pydicom
import datetime
@@ -118,6 +120,10 @@ class Long(models.Model):
help_text="If the json cache needs updating", default=False help_text="If the json cache needs updating", default=False
) )
json_creation_time = models.DateTimeField(blank=True, default=None)
#question_file = models.FileField(upload_to=question_file_directory_path, blank=True, null=True)
def get_absolute_url(self): def get_absolute_url(self):
return reverse("longs:question_detail", kwargs={"pk": self.pk}) return reverse("longs:question_detail", kwargs={"pk": self.pk})
@@ -164,35 +170,64 @@ class Long(models.Model):
return [ans for ans in answers if not ans.is_marked()] return [ans for ans in answers if not ans.is_marked()]
def get_json(self, question_id): def get_json(self, question_id):
# self == q?
q = get_object_or_404(Long, pk=question_id) q = get_object_or_404(Long, pk=question_id)
#exam_order.append(q.id) #exam_order.append(q.id)
path= "{0}longs/questions/{1}.json".format(settings.MEDIA_ROOT, question_id)
url= "{0}longs/questions/{1}.json".format(settings.MEDIA_URL, question_id)
# Loop through longimage associations timestamp = datetime.datetime.now()
images = [] with open(path, "w+") as f:
image_titles = []
for series in q.series.all():
#image_array = []
#for i in series.images.all():
# image_array.append(image_as_base64(i.image))
# #image_array.append(i.image.url)
image_array = [image_as_base64(i.image) for i in series.images.all()]
images.append(image_array)
image_titles.append(series.get_examination())
# We manually create the json for long questions to reducem memroy usade
f.write("""{{
exam_question = { "title": "{}",
"title": q.history,
"images": images,
"image_titles": image_titles,
#"feedback_image": [],
#"annotations": [str(q.image_annotations)],
"type": "long", "type": "long",
"cached": False, "generated": "{}",
} """.format(q.history, timestamp.isoformat())
)
return exam_question
f.write('"images" : [')
#images = []
image_titles = []
question_series = q.series.all()
# Loop through longimage associations
for i, series in enumerate(question_series):
#image_array = []
#for i in series.images.all():
# image_array.append(image_as_base64(i.image))
# #image_array.append(i.image.url)
# We are still limited by the size of a series (although this should not be too big or computers will crash...)
image_array = [image_as_base64(i.image) for i in series.images.all()]
#image_array = [i.image.url for i in series.images.all()]
f.write(json.dumps(image_array))
#images.append(url)
if i != len(question_series) - 1:
f.write(",")
image_titles.append(series.get_examination())
f.write("],")
f.write('"image_titles" : {} }}'.format(json.dumps(image_titles)))
self.json_creation_time = timestamp
self.save()
#exam_question = {
# "title": q.history,
# "images": images,
# "image_titles": image_titles,
# #"feedback_image": [],
# #"annotations": [str(q.image_annotations)],
# "type": "long",
# "cached": False,
#}
return url
@@ -482,6 +517,7 @@ class Exam(ExamBase):
#"feedback_image": [], #"feedback_image": [],
#"annotations": [str(q.image_annotations)], #"annotations": [str(q.image_annotations)],
"type": "long", "type": "long",
"images_json": True,
} }
return exam_question return exam_question
@@ -498,7 +534,7 @@ class Exam(ExamBase):
for q in questions: for q in questions:
exam_order.append(q.id) exam_order.append(q.id)
exam_questions[q.id] = n exam_questions[q.id] = q.json_creation_time.isoformat()
continue continue
@@ -538,7 +574,7 @@ class Exam(ExamBase):
"exam_mode": True, "exam_mode": True,
"exam_order": exam_order, "exam_order": exam_order,
"questions": exam_questions, "questions": exam_questions,
"question_requests": True, "question_requests": exam_questions,
} }
@@ -53,5 +53,8 @@
</ul> </ul>
</div> </div>
<div>
JSON creation time: {{question.json_creation_time}} ({{question.json_creation_time|date:"c"}})
</div>
<a href="{% url 'longs:question_json' pk=question.pk %}">JSON</a> <a href="{% url 'longs:question_json' pk=question.pk %}">JSON</a>
<a href="{% url 'longs:question_json_recreate' pk=question.pk %}">Refresh JSON cache</a> <a href="{% url 'longs:question_json_recreate' pk=question.pk %}">Refresh JSON cache</a>
+10 -7
View File
@@ -47,6 +47,7 @@ import statistics
import plotly.express as px import plotly.express as px
from django.core.cache import cache from django.core.cache import cache
from django.conf import settings
from helpers.images import image_as_base64 from helpers.images import image_as_base64
@@ -63,6 +64,8 @@ from rest_framework import viewsets
from .serializers import ExamSerializer from .serializers import ExamSerializer
import os
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -993,20 +996,18 @@ def question_json(request, pk):
#if not exam.active: #if not exam.active:
# raise Http404("No available exam") # raise Http404("No available exam")
question_json_cache = cache.get("{}_question_json_{}".format("longs", pk)) path= "{0}longs/questions/{1}.json".format(settings.MEDIA_ROOT, pk)
url= "{0}longs/questions/{1}.json".format(settings.MEDIA_URL, pk)
if question_json_cache is not None and not question.recreate_json: if os.path.isfile(path) and not question.recreate_json:
question_json_cache["cached"] = True return redirect(url)
return JsonResponse(question_json_cache)
question_json = question.get_json(pk) question_json = question.get_json(pk)
cache.set("{}_question_json_{}".format("longs", pk), question_json, 3600)
question.recreate_json = False question.recreate_json = False
question.save() question.save()
return JsonResponse(question_json) return redirect(question_json)
@login_required @login_required
def question_json_recreate(request, pk): def question_json_recreate(request, pk):
@@ -1015,4 +1016,6 @@ def question_json_recreate(request, pk):
question.recreate_json = True question.recreate_json = True
question.save() question.save()
question.get_json(pk)
return redirect("longs:question_detail", pk=pk) return redirect("longs:question_detail", pk=pk)
@@ -0,0 +1,18 @@
# Generated by Django 3.1.3 on 2021-03-09 15:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('physics', '0003_auto_20201228_2235'),
]
operations = [
migrations.AddField(
model_name='exam',
name='json_creation_time',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 3.1.3 on 2021-03-09 15:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rapids', '0019_auto_20210215_1203'),
]
operations = [
migrations.AddField(
model_name='exam',
name='json_creation_time',
field=models.DateTimeField(blank=True, default=None, null=True),
),
]