diff --git a/anatomy/filters.py b/anatomy/filters.py
index 8358550f..b5995911 100644
--- a/anatomy/filters.py
+++ b/anatomy/filters.py
@@ -1,6 +1,22 @@
import django_filters
-from .models import AnatomyQuestion
+from .models import AnatomyQuestion, CidUserAnswer
+
+#from generic.filters import UserAnswerFilter
+
+
+class AnatomyUserAnswerFilter(django_filters.FilterSet):
+ class Meta:
+ model= CidUserAnswer
+ fields = (
+ "cid",
+ "question",
+ "answer",
+ #"answer_compare",
+ "exam",
+ "created",
+ "updated",
+ )
class AnatomyQuestionFilter(django_filters.FilterSet):
diff --git a/anatomy/migrations/0029_auto_20210209_2239.py b/anatomy/migrations/0029_auto_20210209_2239.py
new file mode 100644
index 00000000..60fc1770
--- /dev/null
+++ b/anatomy/migrations/0029_auto_20210209_2239.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.1.3 on 2021-02-09 22:39
+
+import anatomy.models
+import django.core.files.storage
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('anatomy', '0028_auto_20210206_0905'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='anatomyquestion',
+ name='image',
+ field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/anatomy/', location='/home/ross/rad/media//anatomy/'), upload_to=anatomy.models.image_directory_path),
+ ),
+ ]
diff --git a/anatomy/models.py b/anatomy/models.py
index cc3f74c0..4dc61b51 100644
--- a/anatomy/models.py
+++ b/anatomy/models.py
@@ -310,41 +310,6 @@ class Exam(ExamBase):
return exam_json
-# class UserAnswer(models.Model):
-# question = models.ForeignKey(
-# AnatomyQuestion, related_name="user_answers", on_delete=models.CASCADE
-# )
-# answer = models.TextField(max_length=500, blank=True)
-# user = models.ForeignKey(
-# settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL
-# )
-
-# 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="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.GetPrimaryAnswer(), self.answer
-# )
-
-# def clean(self):
-# if self.answer:
-# self.answer = self.answer.strip()
-
-
class CidUserAnswer(models.Model):
"""User answers by candidate"""
diff --git a/anatomy/tables.py b/anatomy/tables.py
index c3994922..181be430 100644
--- a/anatomy/tables.py
+++ b/anatomy/tables.py
@@ -1,7 +1,7 @@
import django_tables2 as tables
from django_tables2.utils import A
-from .models import AnatomyQuestion
+from .models import AnatomyQuestion, CidUserAnswer
from django.utils.html import format_html
@@ -9,6 +9,27 @@ from easy_thumbnails.files import get_thumbnailer
from easy_thumbnails.exceptions import InvalidImageFormatError
+#from generic.tables import UserAnswerTable
+
+
+class AnatomyUserAnswerTable(tables.Table):
+ select = tables.CheckBoxColumn(accessor=("pk"))
+ delete = tables.LinkColumn(
+ "anatomy:anatomy_user_answer_delete", text="Delete", args=[A("pk")], orderable=False
+ )
+ class Meta:
+ model = CidUserAnswer
+ template_name = "django_tables2/bootstrap4.html"
+ fields = (
+ "cid",
+ "question",
+ "answer",
+ #"answer_compare",
+ "exam",
+ "created",
+ "updated",
+ )
+
class ImageColumn(tables.Column):
def render(self, value):
diff --git a/anatomy/templates/anatomy/ciduseranswer_confirm_delete.html b/anatomy/templates/anatomy/ciduseranswer_confirm_delete.html
new file mode 100644
index 00000000..41ddc888
--- /dev/null
+++ b/anatomy/templates/anatomy/ciduseranswer_confirm_delete.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/anatomy/urls.py b/anatomy/urls.py
index 0c4202fc..d27dd7a8 100644
--- a/anatomy/urls.py
+++ b/anatomy/urls.py
@@ -51,4 +51,6 @@ urlpatterns = [
path("examination/ajax/get_examination_id",
views.get_examination_id,
name="get_examination_id"),
+ path("user_answers/", views.AnatomyUserAnswerView.as_view(), name="anatomy_user_answer_view"),
+ path("user_answers//delete", views.UserAnswerDelete.as_view(), name="anatomy_user_answer_delete"),
]
diff --git a/anatomy/views.py b/anatomy/views.py
index f83dbfc9..bf303ab7 100644
--- a/anatomy/views.py
+++ b/anatomy/views.py
@@ -46,8 +46,8 @@ from .models import (
from generic.models import Examination
from generic.views import ExamViews
-from .tables import AnatomyQuestionTable
-from .filters import AnatomyQuestionFilter
+from .tables import AnatomyQuestionTable, AnatomyUserAnswerTable
+from .filters import AnatomyQuestionFilter, AnatomyUserAnswerFilter
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
@@ -62,6 +62,8 @@ from helpers.images import image_as_base64
from django.template.defaulttags import register
+from generic.mixins import SuperuserRequiredMixin
+
@register.filter
def get_item(dictionary, key):
@@ -919,6 +921,13 @@ class AnatomyQuestionView(SingleTableMixin, FilterView):
filterset_class = AnatomyQuestionFilter
+class AnatomyUserAnswerView(SingleTableMixin, FilterView):
+ model = CidUserAnswer
+ table_class = AnatomyUserAnswerTable
+ template_name = "anatomy/anatomy_question_view.html"
+
+ filterset_class = AnatomyUserAnswerFilter
+
def question_save_annotation(request, pk):
if request.is_ajax() and request.method == "POST":
@@ -935,4 +944,8 @@ def question_save_annotation(request, pk):
return JsonResponse(data, status=400)
-AnatomyExamViews = ExamViews(Exam, "anatomy", "anatomy", loadJsonAnswer)
\ No newline at end of file
+AnatomyExamViews = ExamViews(Exam, "anatomy", "anatomy", loadJsonAnswer)
+
+class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
+ model = CidUserAnswer
+ success_url = reverse_lazy("anatomy:anatomy_user_answer_view")
\ No newline at end of file
diff --git a/generic/filters.py b/generic/filters.py
new file mode 100644
index 00000000..3eddff2e
--- /dev/null
+++ b/generic/filters.py
@@ -0,0 +1,18 @@
+import django_filters
+
+
+
+#class UserAnswerFilter(django_filters.FilterSet):
+# class Meta:
+# #model = AnatomyQuestion
+# abstract = True
+# fields = (
+# "cid",
+# "question",
+# "answer",
+# #"answer_compare",
+# "exam",
+# "created",
+# "updateded",
+# "created_date",
+# )
\ No newline at end of file
diff --git a/generic/mixins.py b/generic/mixins.py
new file mode 100644
index 00000000..875aa998
--- /dev/null
+++ b/generic/mixins.py
@@ -0,0 +1,6 @@
+from django.contrib.auth.mixins import UserPassesTestMixin
+
+
+class SuperuserRequiredMixin(UserPassesTestMixin):
+ def test_func(self):
+ return self.request.user.is_superuser
\ No newline at end of file
diff --git a/generic/tables.py b/generic/tables.py
new file mode 100644
index 00000000..e87ae678
--- /dev/null
+++ b/generic/tables.py
@@ -0,0 +1,47 @@
+import django_tables2 as tables
+from django_tables2.utils import A
+
+from django.utils.html import format_html
+
+from easy_thumbnails.files import get_thumbnailer
+
+from easy_thumbnails.exceptions import InvalidImageFormatError
+
+
+class ImageColumn(tables.Column):
+ def render(self, value):
+ try:
+ thumbnailer = get_thumbnailer(value)
+ return format_html('
', thumbnailer["exam-list"])
+ except InvalidImageFormatError:
+ return format_html('Invalid image url', value)
+
+
+#class UserAnswerTable(tables.Table):
+# #edit = tables.LinkColumn(
+# # "anatomy:anatomy_question_update", text="Edit", args=[A("pk")], orderable=False
+# #)
+# #view = tables.LinkColumn(
+# # "anatomy:question_detail", text="View", args=[A("pk")], orderable=False
+# #)
+# #image = ImageColumn("image", orderable=False)
+# # clone = tables.LinkColumn('anatomy:anatomy_question_clone',
+# # text='Clone',
+# # args=[A('pk')],
+# # orderable=False)
+# #exams = tables.ManyToManyColumn(verbose_name="Exams")
+#
+# class Meta:
+# #model = AnatomyQuestion
+# abstract = True
+# template_name = "django_tables2/bootstrap4.html"
+# fields = (
+# "cid",
+# "question",
+# "answer",
+# #"answer_compare",
+# "exam",
+# "created",
+# "updated",
+# )
+# #sequence = ("view")
\ No newline at end of file
diff --git a/generic/views.py b/generic/views.py
index a72fe095..ed517883 100644
--- a/generic/views.py
+++ b/generic/views.py
@@ -210,7 +210,7 @@ class ExamViews(View, LoginRequiredMixin):
return JsonResponse(active_exams)
@method_decorator(csrf_exempt)
- def postExamAnswers(request):
+ def postExamAnswers(self, request):
if request.is_ajax and request.method == "POST":
n = 0
diff --git a/helpers/images.py b/helpers/images.py
index b3344920..2712b028 100644
--- a/helpers/images.py
+++ b/helpers/images.py
@@ -21,6 +21,8 @@ def image_as_base64(image_file):
# encoded_string = base64.b64encode(img_f.read())
encoded_string = base64.b64encode(image_file.file.read())
mimetype, enc = mimetypes.guess_type(image_file.path)
+ if "dicom" in mimetype:
+ return "data:{};base64,{}".format(mimetype, encoded_string.decode("utf-8"))
return "data:image/{};base64,{}".format(mimetype, encoded_string.decode("utf-8"))
@@ -54,4 +56,4 @@ def pil_dicom_image(source, exif_orientation=True, **options):
#if exif_orientation:
# image = utils.exif_orientation(image)
- return image
\ No newline at end of file
+ return image
diff --git a/longs/migrations/0014_auto_20210211_1827.py b/longs/migrations/0014_auto_20210211_1827.py
new file mode 100644
index 00000000..414ef2f2
--- /dev/null
+++ b/longs/migrations/0014_auto_20210211_1827.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.1.3 on 2021-02-11 18:27
+
+import django.core.files.storage
+from django.db import migrations, models
+import longs.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('longs', '0013_auto_20210206_2147'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='longseriesimage',
+ name='image',
+ field=models.FileField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/longs/', location='/home/ross/rad/media/longs/'), upload_to=longs.models.image_directory_path),
+ ),
+ ]
diff --git a/longs/models.py b/longs/models.py
index ee6b788b..40fd7934 100644
--- a/longs/models.py
+++ b/longs/models.py
@@ -15,9 +15,13 @@ from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.html import mark_safe
+from django.core.exceptions import ValidationError
+
from sortedm2m.fields import SortedManyToManyField
import string
+from collections import defaultdict
+from helpers.images import image_as_base64
from anatomy.models import Modality
@@ -30,7 +34,7 @@ from easy_thumbnails.exceptions import InvalidImageFormatError
image_storage = FileSystemStorage(
# Physical file location ROOT
- location=u"{0}/longs/".format(settings.MEDIA_ROOT),
+ location=u"{0}longs/".format(settings.MEDIA_ROOT),
# Url for file
base_url=u"{0}longs/".format(settings.MEDIA_URL),
)
@@ -139,8 +143,11 @@ class Long(models.Model):
# return self.GetImages()
+def test_image_validator(file):
+ pass
+
class LongSeriesImage(models.Model):
- image = models.ImageField(upload_to=image_directory_path, storage=image_storage)
+ image = models.FileField(upload_to=image_directory_path, storage=image_storage)
position = models.IntegerField(default=0)
series = models.ForeignKey(
"LongSeries", related_name="images", on_delete=models.SET_NULL, null=True
@@ -200,7 +207,7 @@ class LongSeries(models.Model):
return authors
def get_author_display(self):
- return ", ".join(self.get_author_objects())
+ return ", ".join([i.username for i in self.get_author_objects()])
def get_examination(self):
"""Returns a comma seperated text list of regions"""
@@ -303,6 +310,57 @@ class Exam(ExamBase):
default=4500,
)
+ def get_exam_json(self):
+ questions = self.exam_questions.all()
+
+ exam_questions = defaultdict(dict)
+
+ exam_order = []
+
+ for q in questions:
+ exam_order.append(q.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)
+ images.append(image_array)
+ image_titles.append(series.get_examination())
+
+
+
+ exam_questions[q.id] = {
+ "title": q.history,
+ "images": images,
+ "image_titles": image_titles,
+ #"feedback_image": [],
+ #"annotations": [str(q.image_annotations)],
+ "type": "long",
+ }
+
+ #if feedback_images:
+ # exam_questions[q.id]["feedback_image"] = feedback_images
+
+
+ exam_json = {
+ "eid": "long/{}".format(self.id),
+ "cached": False,
+ "exam_type": "long",
+ "exam_name": self.name,
+ "exam_mode": True,
+ "exam_order": exam_order,
+ "questions": exam_questions,
+ }
+
+
+ if self.time_limit:
+ exam_json["exam_time"] = self.time_limit
+
+ return exam_json
class CidUserAnswer(models.Model):
"""User answers by candidate"""
diff --git a/longs/tables.py b/longs/tables.py
index 64c5a07a..b1119226 100755
--- a/longs/tables.py
+++ b/longs/tables.py
@@ -31,6 +31,9 @@ class LongSeriesImageColumn(tables.Column):
def render(self, value):
obj = value.first()
+ if obj is None:
+ return "None"
+
image_object = obj.image
try:
thumbnailer = get_thumbnailer(image_object)
diff --git a/longs/urls.py b/longs/urls.py
index 07aebd3d..fc8379a9 100755
--- a/longs/urls.py
+++ b/longs/urls.py
@@ -48,7 +48,7 @@ urlpatterns = [
path("exam/submit", views.LongExamViews.postExamAnswers, name="exam_answers_submit"),
path("exam/", views.LongExamViews.exam_list, name="exam_list"),
path("exam/json/", views.LongExamViews.active_exams, name="active_exams"),
- path("exam/json/", views.exam_json, name="exam_json"),
+ path("exam/json/", views.LongExamViews.exam_json, name="exam_json"),
path(
"exam/json//recreate",
views.LongExamViews.exam_json_recreate,
diff --git a/longs/views.py b/longs/views.py
index 500c7c5f..25797fa8 100755
--- a/longs/views.py
+++ b/longs/views.py
@@ -796,75 +796,6 @@ def mark(request, pk, sk):
)
-
-def exam_json(request, pk):
-
- exam = get_object_or_404(Exam, pk=pk)
-
- if not exam.active:
- raise Http404("No available exam")
-
- exam_json_cache = cache.get("longs_exam_json_{}".format(pk))
-
- if exam_json_cache is not None and not exam.recreate_json:
- exam_json_cache["cached"] = True
- return JsonResponse(exam_json_cache)
-
- questions = exam.exam_questions.all()
-
- exam_questions = defaultdict(dict)
-
- exam_order = []
-
- for q in questions:
- exam_order.append(q.id)
-
- # Loop through longimage associations
- images = []
- feedback_images = []
- for i in q.images.all():
- if i.feedback_image == True:
- feedback_images.append(image_as_base64(i.image))
- # feedback_images.append(i.image.url)
- else:
- images.append(image_as_base64(i.image))
- #images.append(i.image.url)
-
-
-
- exam_questions[q.id] = {
- "images": images,
- #"feedback_image": [],
- #"annotations": [str(q.image_annotations)],
- "type": "long",
- }
-
- #if feedback_images:
- # exam_questions[q.id]["feedback_image"] = feedback_images
-
-
- exam_json = {
- "eid": "long/{}".format(exam.id),
- "cached": False,
- "exam_type": "long",
- "exam_name": exam.name,
- "exam_mode": True,
- "exam_order": exam_order,
- "questions": exam_questions,
- }
-
-
- if exam.time_limit:
- exam_json["exam_time"] = exam.time_limit
-
- exam.recreate_json = False
- exam.save()
-
- cache.set("longs_exam_json_{}".format(pk), exam_json, 3600)
-
- return JsonResponse(exam_json)
-
-
@login_required
def exam_scores_cid(request, pk):
exam = get_object_or_404(Exam, pk=pk)
diff --git a/rad/settings.py b/rad/settings.py
index ca177d50..05c3238d 100644
--- a/rad/settings.py
+++ b/rad/settings.py
@@ -50,6 +50,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'debug_toolbar',
"tagulous",
+ "dbbackup",
]
MIDDLEWARE = [
@@ -199,8 +200,14 @@ THUMBNAIL_ALIASES = {
}
THUMBNAIL_SOURCE_GENERATORS = ('easy_thumbnails.source_generators.pil_image', 'helpers.images.pil_dicom_image')
+DBBACKUP_STORAGE = 'django.core.files.storage.FileSystemStorage'
+DBBACKUP_STORAGE_OPTIONS = {'location': os.path.join(BASE_DIR, '../backups')}
try:
from .settings_local import *
except ImportError:
pass
+<<<<<<< HEAD
+=======
+
+>>>>>>> 5763aae287cbceee318f975495f7d9429517c88f
diff --git a/rapids/migrations/0013_auto_20210209_2239.py b/rapids/migrations/0013_auto_20210209_2239.py
new file mode 100644
index 00000000..31981c9a
--- /dev/null
+++ b/rapids/migrations/0013_auto_20210209_2239.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.1.3 on 2021-02-09 22:39
+
+import django.core.files.storage
+from django.db import migrations, models
+import rapids.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('rapids', '0012_auto_20210206_0905'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='rapidimage',
+ name='image',
+ field=models.ImageField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/rapids/', location='/home/ross/rad/media//rapids/'), upload_to=rapids.models.image_directory_path),
+ ),
+ ]
diff --git a/rapids/migrations/0014_auto_20210211_2034.py b/rapids/migrations/0014_auto_20210211_2034.py
new file mode 100644
index 00000000..d6fc2db2
--- /dev/null
+++ b/rapids/migrations/0014_auto_20210211_2034.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.1.3 on 2021-02-11 20:34
+
+import django.core.files.storage
+from django.db import migrations, models
+import rapids.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('rapids', '0013_auto_20210209_2239'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='rapidimage',
+ name='image',
+ field=models.FileField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/rapids/', location='/home/ross/rad/media//rapids/'), upload_to=rapids.models.image_directory_path),
+ ),
+ ]
diff --git a/rapids/migrations/0015_auto_20210211_2035.py b/rapids/migrations/0015_auto_20210211_2035.py
new file mode 100644
index 00000000..2743692c
--- /dev/null
+++ b/rapids/migrations/0015_auto_20210211_2035.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.1.3 on 2021-02-11 20:35
+
+import django.core.files.storage
+from django.db import migrations, models
+import rapids.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('rapids', '0014_auto_20210211_2034'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='rapidimage',
+ name='image',
+ field=models.FileField(storage=django.core.files.storage.FileSystemStorage(base_url='/media/rapids/', location='/home/ross/rad/media/rapids/'), upload_to=rapids.models.image_directory_path),
+ ),
+ ]
diff --git a/rapids/models.py b/rapids/models.py
index 6c8edbce..75754638 100644
--- a/rapids/models.py
+++ b/rapids/models.py
@@ -16,13 +16,15 @@ from django.utils.html import mark_safe
from sortedm2m.fields import SortedManyToManyField
import string
+from collections import defaultdict
+from helpers.images import image_as_base64
from generic.models import Site, Condition, Sign, ExamBase
image_storage = FileSystemStorage(
# Physical file location ROOT
- location=u"{0}/rapids/".format(settings.MEDIA_ROOT),
+ location=u"{0}rapids/".format(settings.MEDIA_ROOT),
# Url for file
base_url=u"{0}rapids/".format(settings.MEDIA_URL),
)
@@ -286,7 +288,7 @@ class RapidImage(models.Model):
rapid = models.ForeignKey(Rapid,
related_name="images",
on_delete=models.CASCADE)
- image = models.ImageField(upload_to=image_directory_path, storage=image_storage)
+ image = models.FileField(upload_to=image_directory_path, storage=image_storage)
feedback_image = models.BooleanField(default=False)
@@ -350,6 +352,55 @@ class Exam(ExamBase):
help_text="Exam time limit (in seconds). Default is 2100 secondse (35 minutes)", default=2100
)
+ def get_exam_json(self):
+ questions = self.exam_questions.all()
+
+ exam_questions = defaultdict(dict)
+
+ exam_order = []
+
+ for q in questions:
+ exam_order.append(q.id)
+
+ # Loop through rapidimage associations
+ images = []
+ feedback_images = []
+ for i in q.images.all():
+ if i.feedback_image == True:
+ feedback_images.append(image_as_base64(i.image))
+ # feedback_images.append(i.image.url)
+ else:
+ images.append(image_as_base64(i.image))
+ #images.append(i.image.url)
+
+
+
+ exam_questions[q.id] = {
+ "images": images,
+ #"feedback_image": [],
+ #"annotations": [str(q.image_annotations)],
+ "type": "rapid",
+ }
+
+ #if feedback_images:
+ # exam_questions[q.id]["feedback_image"] = feedback_images
+
+
+ exam_json = {
+ "eid": "rapid/{}".format(self.id),
+ "cached": False,
+ "exam_type": "rapid",
+ "exam_name": self.name,
+ "exam_mode": True,
+ "exam_order": exam_order,
+ "questions": exam_questions,
+ }
+
+ if self.time_limit:
+ exam_json["exam_time"] = self.time_limit
+
+ return exam_json
+
class CidUserAnswer(models.Model):
"""User answers by candidate"""
diff --git a/rapids/urls.py b/rapids/urls.py
index a5df6aec..32acb33d 100755
--- a/rapids/urls.py
+++ b/rapids/urls.py
@@ -32,7 +32,7 @@ urlpatterns = [
path("exam/submit", views.RapidExamViews.postExamAnswers, name="exam_answers_submit"),
path("exam/", views.RapidExamViews.exam_list, name="exam_list"),
path("exam/json/", views.RapidExamViews.active_exams, name="active_exams"),
- path("exam/json/", views.exam_json, name="exam_json"),
+ path("exam/json/", views.RapidExamViews.exam_json, name="exam_json"),
path("exam/json//recreate", views.RapidExamViews.exam_json_recreate, name="exam_json_recreate"),
path("create/", views.RapidCreate.as_view(), name="rapid_create"),
path("create/defaults",
diff --git a/rapids/views.py b/rapids/views.py
index 6e761d0c..ba4dab7e 100755
--- a/rapids/views.py
+++ b/rapids/views.py
@@ -699,73 +699,6 @@ def mark(request, pk, sk):
)
-def exam_json(request, pk):
-
- exam = get_object_or_404(Exam, pk=pk)
-
- if not exam.active:
- raise Http404("No available exam")
-
- exam_json_cache = cache.get("rapids_exam_json_{}".format(pk))
-
- if exam_json_cache is not None and not exam.recreate_json:
- exam_json_cache["cached"] = True
- return JsonResponse(exam_json_cache)
-
- questions = exam.exam_questions.all()
-
- exam_questions = defaultdict(dict)
-
- exam_order = []
-
- for q in questions:
- exam_order.append(q.id)
-
- # Loop through rapidimage associations
- images = []
- feedback_images = []
- for i in q.images.all():
- if i.feedback_image == True:
- feedback_images.append(image_as_base64(i.image))
- # feedback_images.append(i.image.url)
- else:
- images.append(image_as_base64(i.image))
- #images.append(i.image.url)
-
-
-
- exam_questions[q.id] = {
- "images": images,
- #"feedback_image": [],
- #"annotations": [str(q.image_annotations)],
- "type": "rapid",
- }
-
- #if feedback_images:
- # exam_questions[q.id]["feedback_image"] = feedback_images
-
-
- exam_json = {
- "eid": "rapid/{}".format(exam.id),
- "cached": False,
- "exam_type": "rapid",
- "exam_name": exam.name,
- "exam_mode": True,
- "exam_order": exam_order,
- "questions": exam_questions,
- }
-
- if exam.time_limit:
- exam_json["exam_time"] = exam.time_limit
-
- exam.recreate_json = False
- exam.save()
-
- cache.set("rapids_exam_json_{}".format(pk), exam_json, 3600)
-
- return JsonResponse(exam_json)
-
-
@login_required
def exam_scores_cid(request, pk):
exam = get_object_or_404(Exam, pk=pk)
diff --git a/requirements.txt b/requirements.txt
index a77810be..7ecc51d5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,4 +14,5 @@ psycopg2-binary
django-sortedm2m
pytesseract
opencv-python
-pydicom
\ No newline at end of file
+pydicom
+django-dbbackup