Merge branch 'master' of ssh://git.xkjq.uk:30001/ross/rad
This commit is contained in:
@@ -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),
|
||||
),
|
||||
]
|
||||
@@ -64,6 +64,8 @@ class ExamBase(models.Model):
|
||||
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(
|
||||
# help_text="Exam time limit (in seconds). Default is 2100 secondse (35 minutes)",
|
||||
# default=2100,
|
||||
|
||||
+45
-11
@@ -32,6 +32,10 @@ from anatomy.models import AnatomyQuestion as AnatomyQuestion
|
||||
from anatomy.models import Exam as AnatomyExam
|
||||
|
||||
from django.db.models import Case, When
|
||||
from django.conf import settings
|
||||
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
|
||||
# Create your views here.
|
||||
@@ -177,6 +181,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
exam.recreate_json = True
|
||||
exam.save()
|
||||
|
||||
exam.get_exam_json()
|
||||
|
||||
return redirect("{}:exam_overview".format(self.app_name), pk=pk)
|
||||
|
||||
@method_decorator(login_required)
|
||||
@@ -315,13 +321,25 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
|
||||
for exam in exams:
|
||||
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(),
|
||||
"url": request.build_absolute_uri(exam.get_json_url()),
|
||||
"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:
|
||||
return active_exams["exams"]
|
||||
@@ -356,24 +374,37 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
if not exam.active:
|
||||
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["cached"] = True
|
||||
#exam_json_cache = cache.get("{}_exam_json_{}".format(self.app_name, pk))
|
||||
|
||||
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)
|
||||
|
||||
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.json_creation_time = time
|
||||
exam.save()
|
||||
|
||||
# We also try to clear the cache of any associated questions (longs)
|
||||
# see exam_question_json
|
||||
n = exam.exam_questions.count()
|
||||
question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)]
|
||||
cache.delete_many(question_keys)
|
||||
#n = exam.exam_questions.count()
|
||||
#question_keys = ["{}_exam_json_{}_{}".format(self.app_name, pk, i) for i in range(1, n)]
|
||||
#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)
|
||||
|
||||
@@ -384,6 +415,9 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
if not exam.active:
|
||||
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))
|
||||
|
||||
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
@@ -1,3 +1,4 @@
|
||||
import json
|
||||
from django.db.models.fields.files import ImageField
|
||||
from django.db.models.fields.related import ForeignKey
|
||||
from django.db import models
|
||||
@@ -34,6 +35,7 @@ from easy_thumbnails.files import get_thumbnailer
|
||||
from easy_thumbnails.exceptions import InvalidImageFormatError
|
||||
|
||||
import pydicom
|
||||
import datetime
|
||||
|
||||
|
||||
|
||||
@@ -118,6 +120,10 @@ class Long(models.Model):
|
||||
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):
|
||||
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()]
|
||||
|
||||
def get_json(self, question_id):
|
||||
# self == q?
|
||||
q = get_object_or_404(Long, pk=question_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
|
||||
images = []
|
||||
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())
|
||||
timestamp = datetime.datetime.now()
|
||||
with open(path, "w+") as f:
|
||||
|
||||
|
||||
|
||||
exam_question = {
|
||||
"title": q.history,
|
||||
"images": images,
|
||||
"image_titles": image_titles,
|
||||
#"feedback_image": [],
|
||||
#"annotations": [str(q.image_annotations)],
|
||||
# We manually create the json for long questions to reducem memroy usade
|
||||
f.write("""{{
|
||||
"title": "{}",
|
||||
"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": [],
|
||||
#"annotations": [str(q.image_annotations)],
|
||||
"type": "long",
|
||||
"images_json": True,
|
||||
}
|
||||
|
||||
return exam_question
|
||||
@@ -498,7 +534,7 @@ class Exam(ExamBase):
|
||||
for q in questions:
|
||||
exam_order.append(q.id)
|
||||
|
||||
exam_questions[q.id] = n
|
||||
exam_questions[q.id] = q.json_creation_time.isoformat()
|
||||
|
||||
continue
|
||||
|
||||
@@ -538,7 +574,7 @@ class Exam(ExamBase):
|
||||
"exam_mode": True,
|
||||
"exam_order": exam_order,
|
||||
"questions": exam_questions,
|
||||
"question_requests": True,
|
||||
"question_requests": exam_questions,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -53,5 +53,8 @@
|
||||
</ul>
|
||||
|
||||
</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_recreate' pk=question.pk %}">Refresh JSON cache</a>
|
||||
+10
-7
@@ -47,6 +47,7 @@ import statistics
|
||||
import plotly.express as px
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
|
||||
from helpers.images import image_as_base64
|
||||
|
||||
@@ -63,6 +64,8 @@ from rest_framework import viewsets
|
||||
|
||||
from .serializers import ExamSerializer
|
||||
|
||||
import os
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -993,20 +996,18 @@ def question_json(request, pk):
|
||||
#if not exam.active:
|
||||
# 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:
|
||||
question_json_cache["cached"] = True
|
||||
return JsonResponse(question_json_cache)
|
||||
if os.path.isfile(path) and not question.recreate_json:
|
||||
return redirect(url)
|
||||
|
||||
question_json = question.get_json(pk)
|
||||
|
||||
cache.set("{}_question_json_{}".format("longs", pk), question_json, 3600)
|
||||
|
||||
question.recreate_json = False
|
||||
question.save()
|
||||
|
||||
return JsonResponse(question_json)
|
||||
return redirect(question_json)
|
||||
|
||||
@login_required
|
||||
def question_json_recreate(request, pk):
|
||||
@@ -1015,4 +1016,6 @@ def question_json_recreate(request, pk):
|
||||
question.recreate_json = True
|
||||
question.save()
|
||||
|
||||
question.get_json(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),
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user