Files
penracourses/anatomy/views.py
T
Ross d8167aa95f .
2021-02-05 11:10:59 +00:00

1144 lines
32 KiB
Python

from django.forms.models import model_to_dict
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.csrf import csrf_exempt
from django import forms
# from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.models import User
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import ListView
from django.db.models.functions import Lower
from django.core.cache import cache
from django.urls import reverse_lazy, reverse
from django.http import Http404, JsonResponse
from django.http import HttpResponseRedirect, HttpResponse
from .forms import (
AnatomyAnswerForm,
AnswerFormSet,
AnswerUpdateFormSet,
BodyPartForm,
ExaminationForm,
MarkAnatomyQuestionForm,
AnatomyQuestionForm,
StructureForm,
)
from .models import (
AnatomyQuestion,
BodyPart,
CidUserAnswer,
#Examination,
Structure,
Exam,
Answer,
# HalfMarkAnswers,
# IncorrectAnswers,
)
from generic.models import Examination
from .tables import AnatomyQuestionTable
from .filters import AnatomyQuestionFilter
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
from collections import defaultdict
import os
import json
import statistics
import plotly.express as px
from helpers.images import image_as_base64
from django.template.defaulttags import register
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
def user_is_admin(user):
if user:
if user.pk == 1:
return True
return False
def question_list(request):
questions = AnatomyQuestion.objects.all()
return render(request, "anatomy/question_list.html", {"questions": questions})
@login_required
def index(request):
exams = Exam.objects.all()
return render(request, "anatomy/index.html", {"exams": exams})
@login_required
def question_detail(request, pk):
question = get_object_or_404(AnatomyQuestion, pk=pk)
return render(request, "anatomy/question_detail.html", {"question": question})
@login_required
def exam_question_detail(request, pk, sk):
exam = get_object_or_404(Exam, pk=pk)
question = exam.exam_questions.all()[sk]
exam_length = len(exam.exam_questions.all())
pos = exam.get_question_index(question) + 1
print(question.exams.through.sort_value)
previous = -1
if sk > 0:
previous = sk - 1
next = sk + 1
if sk == exam_length - 1:
next = False
return render(
request,
"anatomy/question_detail.html",
{
"question": question,
"exam": exam,
"next": next,
"previous": previous,
"exam_length": exam_length,
"pos": pos,
},
)
@login_required
def answer_question(request, pk):
question = get_object_or_404(AnatomyQuestion, pk=pk)
answer = question.user_answers.filter(
user=request.user
).first() # .filter(user=User)
if request.method == "POST":
if answer:
form = AnatomyAnswerForm(request.POST, instance=answer)
else:
form = AnatomyAnswerForm(request.POST)
if form.is_valid():
answer = form.save(commit=False)
answer.user = request.user
answer.question = question
# answer.published_date = timezone.now()
answer.save()
return redirect("question_detail", pk=pk)
else:
form = AnatomyAnswerForm(instance=answer)
return render(
request, "anatomy/answer_question.html", {"form": form, "question": question}
)
@login_required
def exam_list(request):
exams = Exam.objects.all()
return render(request, "anatomy/exam_list.html", {"exams": exams})
@login_required
def exam_overview(request, pk):
print(type(pk))
#print(Exam.objects.all())
#exams = Exam.objects.all()
#print("test", Exam.objects.all().get(id=pk))
exam = get_object_or_404(Exam, pk=pk)
print("exam", exam)
questions = exam.exam_questions.all()
question_number = len(questions)
return render(
request,
"anatomy/exam_overview.html",
{"exam": exam, "questions": questions, "question_number": question_number},
)
@login_required
def exam_take(request, pk, sk):
"""
Allows taking of the exam on the django server (when logged in)
No longer used (deprecated in favour of using RTS)
"""
exam = get_object_or_404(Exam, pk=pk)
questions = exam.exam_questions.all()
try:
question = questions[sk]
except IndexError:
raise Http404("Exam question does not exist")
n = sk
question_details = {
"total": len(questions),
"current": n + 1,
}
# Get data for flagged
# answered_questions = UserAnswer.objects.filter(user=request.user).values_list("question__pk", flat=True)
user_answer_data = UserAnswer.objects.filter(user=request.user).values_list(
"question__pk", "answer", "flagged"
)
# flagged_questions = UserAnswer.objects.filter(user=request.user, flagged=True).values_list("question__pk", flat=True)
# flagged_questions I= UserAnswer.filter(user=request.user, ).values_list("question__pk", flat=True)
answered_questions = set()
flagged_questions = set()
for ans_pk, answer, flagged in user_answer_data:
if len(answer.strip()) > 0:
answered_questions.add(ans_pk)
if flagged:
flagged_questions.add(ans_pk)
# u = question.user_answers
answer = question.user_answers.filter(
user=request.user
).first() # .filter(user=User)
if request.method == "POST":
if answer:
form = AnatomyAnswerForm(request.POST, instance=answer)
else:
form = AnatomyAnswerForm(request.POST)
if form.is_valid():
answer = form.save(commit=False)
answer.user = request.user
answer.question = question
# answer.published_date = timezone.now()
answer.save()
if "next" in request.POST:
return redirect("anatomy:exam_take", pk=pk, sk=n + 1)
elif "previous" in request.POST:
return redirect("anatomy:exam_take", pk=pk, sk=n - 1)
else:
form = AnatomyAnswerForm(instance=answer)
return render(
request,
"anatomy/exam.html",
{
"exam": exam,
"form": form,
"question": question,
"question_details": question_details,
"questions": questions,
"flagged_questions": flagged_questions,
"answered_questions": answered_questions,
"answer": answer,
},
)
def flag_question(request):
pk = request.GET.get("pk", None)
ans = UserAnswer.objects.filter(user=request.user, question__pk=pk).first()
ans.flagged = not ans.flagged
ans.save()
data = {"flagged": ans.flagged}
return JsonResponse(data)
def loadJsonAnswer(answer):
# Backend eid is just the object pk number
# in the frontend this is appended with the type
# e.g. anatomy/1
eid = int(answer["eid"].split("/")[1])
# As access is not restricted make sure the data appears valid
if (not isinstance(answer["cid"], int)) or (
not isinstance(eid, int) or (not isinstance(answer["ans"], str))
):
return JsonResponse({"success": False, "error": "cid or eid or answers not defined"})
# The model should catch invalid data but this should be less intensive
max_int = 999999999999999999999
if answer["cid"] > max_int or eid > max_int:
return JsonResponse({"success": False, "error": "invalid cid"})
exam = get_object_or_404(Exam, pk=eid)
if not exam.active:
return JsonResponse(
{"success": False, "error": "No active exam: {}".format(eid)}
)
exiting_answers = CidUserAnswer.objects.filter(
question__id=answer["qid"], exam__id=eid, cid=answer["cid"]
)
if not exiting_answers:
ans = CidUserAnswer(answer=answer["ans"], cid=answer["cid"])
ans.question_id = answer["qid"]
ans.exam_id = eid
ans.full_clean()
ans.save()
else:
# Update an existing answer
# should never be more than one (famous last words)
ans = exiting_answers[0]
ans.answer = answer["ans"]
ans.full_clean()
ans.save()
return True
def exam_json_edit(request, pk):
if request.is_ajax() and request.method == "POST":
exam = get_object_or_404(Exam, pk=pk)
if request.POST.get("set_open_access") == "true":
state = True
else:
state = False
questions_changed = []
for q in exam.exam_questions.all():
q.open_access = state
q.save()
questions_changed.append(q.pk)
data = {"status": "success", "questions": questions_changed, "state": state}
return JsonResponse(data, status=200)
else:
data = {"status": "error"}
return JsonResponse(data, status=400)
@csrf_exempt
def postExamAnswers(request):
if request.is_ajax and request.method == "POST":
n = 0
# horrible but it works
#for k in request.POST.dict():
for answer in json.loads(request.POST.get("answers")):
ret = loadJsonAnswer(answer)
if ret is not True:
return ret
n = n + 1
# print(UserAnswer.objects.filter(exam__id=q["eid"]))
# print(request.urlencode())
return JsonResponse({"success": True, "question_count": n})
return JsonResponse({"success": False, "error": "Invalid data"})
# return render(request, "anatomy/exam.html", {"exam" : exam, "question" : question})
# @user_passes_test(user_is_admin, login_url="/accounts/login")
@login_required
def mark_overview(request, pk):
exam = get_object_or_404(Exam, pk=pk)
questions = exam.exam_questions.all()
return render(
request, "anatomy/mark_overview.html", {"exam": exam, "questions": questions}
)
# @user_passes_test(user_is_admin, login_url="/accounts/login")
@login_required
def mark(request, pk, sk):
exam = get_object_or_404(Exam, pk=pk)
questions = exam.exam_questions.all()
n = sk
question_details = {
"total": len(questions),
"current": n + 1,
}
try:
question = questions[sk]
except IndexError:
raise Http404("Exam question does not exist")
answers_dict = {}
for ans in question.answers.all():
answers_dict[ans.answer_compare] = ans
marked_answers_set = set(answers_dict.keys())
# correct_answers = [i.answer.lower() for i in question.answers.all()]
# half_correct_answers = [
# i.answer.lower() for i in question.half_mark_answers.all()
# ]
# incorrect_answers = [
# i.answer.lower() for i in question.incorrect_answers.all()
# ]
unmarked_user_answers = question.GetUnmarkedAnswers()
if request.method == "POST":
form = MarkAnatomyQuestionForm(request.POST)
# *******************************
# TODO: convert to JSON request
# *******************************
if form.is_valid():
# If skip button is pressed skip the question without marking
if "skip" in request.POST:
return redirect("anatomy:mark", pk=pk, sk=n + 1)
cd = form.cleaned_data
# correct = cd.get("correct")
# half_correct = cd.get("half_correct")
# incorrect = cd.get("incorrect")
marked_answers = json.loads(cd.get("marked_answers"))
## This is mildly dangerous as we delete all answers
# question.answers.all().delete()
# question.half_mark_answers.all().delete()
# question.incorrect_answers.all().delete()
# This should probably use json (or something else...)
# ajax.....
for ans in marked_answers["correct"]:
ans = ans.strip()
if ans == "":
continue
a = Answer.objects.filter(
answer__iexact=ans, question_id=question.pk
).first()
if a is None:
a = Answer()
a.question_id = question.pk
a.answer = ans
a.status = Answer.MarkOptions.CORRECT
a.save()
# for ans in half_correct.split("--//--"):
for ans in marked_answers["half-correct"]:
ans = ans.strip()
if ans == "":
continue
a = Answer.objects.filter(
answer__iexact=ans, question_id=question.pk
).first()
if a is None:
a = Answer()
a.question_id = question.pk
a.answer = ans
a.status = Answer.MarkOptions.HALF_MARK
a.save()
for ans in marked_answers["incorrect"]:
ans = ans.strip()
if ans == "":
continue
a = Answer.objects.filter(
answer__iexact=ans, question_id=question.pk
).first()
if a is None:
a = Answer()
a.question_id = question.pk
a.answer = ans
a.status = Answer.MarkOptions.INCORRECT
a.save()
# answer = form.save(commit=False)
# answer.user = request.user
# answer.question = question
# answer.published_date = timezone.now()
# answer.save()
if "next" in request.POST:
return redirect("anatomy:mark", pk=pk, sk=n + 1)
elif "previous" in request.POST:
return redirect("anatomy:mark", pk=pk, sk=n - 1)
# Reset user answers (relies on the functional javascript)
unmarked_user_answers = set()
else:
form = MarkAnatomyQuestionForm()
correct_answers = question.answers.filter(status=Answer.MarkOptions.CORRECT)
half_mark_answers = question.answers.filter(status=Answer.MarkOptions.HALF_MARK)
incorrect_answers = question.answers.filter(status=Answer.MarkOptions.INCORRECT)
return render(
request,
"anatomy/mark.html",
{
"exam": exam,
"form": form,
"question": question,
"question_details": question_details,
"user_answers": unmarked_user_answers,
"correct_answers": correct_answers,
"half_mark_answers": half_mark_answers,
"incorrect_answers": incorrect_answers,
},
)
def exam_toggle_results_published(request, pk):
if request.is_ajax() and request.method == "POST":
exam = get_object_or_404(Exam, pk=pk)
exam.publish_results = (
True if request.POST.get("publish_results") == "true" else False
)
exam.save()
data = {"status": "success", "publish_results": exam.publish_results}
return JsonResponse(data, status=200)
else:
data = {"status": "error"}
return JsonResponse(data, status=400)
def exam_toggle_active(request, pk):
if request.is_ajax() and request.method == "POST":
exam = get_object_or_404(Exam, pk=pk)
exam.active = True if request.POST.get("active") == "true" else False
exam.save()
data = {"status": "success", "active": exam.active}
return JsonResponse(data, status=200)
else:
data = {"status": "error"}
return JsonResponse(data, status=400)
def active_exams(request, json=True):
exams = Exam.objects.all()
active_exams = {"exams": []}
for exam in exams:
if exam.active:
active_exams["exams"].append(
{
"name": exam.get_exam_name(),
"url": request.build_absolute_uri(exam.get_json_url()),
"type": "anatomy",
}
)
if json == False:
return active_exams["exams"]
return JsonResponse(active_exams)
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("anatomy_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)
exam_questions[q.id] = {
"title": "{}".format(q.description),
"question": str(q.question_type),
"images": [image_as_base64(q.image)],
"annotations": [str(q.image_annotations)],
"type": "anatomy",
}
exam_json = {
"eid": "anatomy/{}".format(exam.id),
"cached": False,
"exam_type": "anatomy",
"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("anatomy_exam_json_{}".format(pk), exam_json, 3600)
return JsonResponse(exam_json)
@login_required
def exam_json_recreate(request, pk):
exam = get_object_or_404(Exam, pk=pk)
exam.recreate_json = True
exam.save()
return redirect("anatomy:exam_overview", pk=pk)
@login_required
def exam_scores_cid(request, pk):
exam = get_object_or_404(Exam, pk=pk)
questions = exam.exam_questions.all()
cids = (
CidUserAnswer.objects.filter(question__in=questions)
.order_by("cid")
.values_list("cid", flat=True)
.distinct()
)
user_answers_and_marks = defaultdict(list)
user_answers_marks = defaultdict(list)
user_answers = defaultdict(list)
user_names = {}
by_question = defaultdict(list)
unmarked = set()
# Loop through all candidates
for cid in cids:
# Convoluted (probably...)
user_names[cid] = cid
for q in questions:
# Get user answer
s = q.cid_user_answers.filter(cid=cid).first()
if not s:
# skip if no answer
user_answers_marks[cid].append(0)
user_answers[cid].append("")
by_question[q].append(("", 0))
continue
ans = s.answer
answer_score = s.get_answer_score()
if answer_score == "unmarked":
index = exam.get_question_index(q)
unmarked.add(index)
user_answers[cid].append(ans)
user_answers_marks[cid].append(answer_score)
user_answers_and_marks[cid].append((ans, answer_score))
by_question[q].append((ans, answer_score))
user_scores = {}
for user in user_answers_marks:
user_scores[user] = sum(
[i for i in user_answers_marks[user] if i != "unmarked"]
)
user_scores_list = list(user_scores.values())
if len(user_scores_list) < 1:
mean = 0
median = 0
mode = 0
fig_html = ""
else:
mean = statistics.mean(user_scores_list)
median = statistics.median(user_scores_list)
try:
mode = statistics.mode(user_scores_list)
except statistics.StatisticsError:
mode = "No unique mode"
df = user_scores_list
fig = px.histogram(
df,
x=0,
title="{}: distribution of scores".format(exam),
labels={"0": "Score"},
height=400,
width=600,
)
fig_html = fig.to_html()
max_score = len(questions) * 2
return render(
request,
"anatomy/exam_scores.html",
{
"cids": cids,
"exam": exam,
"unmarked": unmarked,
"questions": questions,
"by_question": by_question,
"user_answers": dict(user_answers),
"user_answers_marks": dict(user_answers_marks),
"user_scores": user_scores,
"user_scores_list": user_scores_list,
"user_names": user_names,
"user_answers_and_marks": user_answers_and_marks,
"max_score": max_score,
"mean": mean,
"median": median,
"mode": mode,
"plot": fig_html,
},
)
def exam_scores_cid_user(request, pk, sk):
exam = get_object_or_404(Exam, pk=pk)
# TODO:Need some kind of test for cid
cid = sk
questions = exam.exam_questions.all()
answers_and_marks = []
answers_marks = []
answers = []
for q in questions:
# Get user answer
user_answer = q.cid_user_answers.filter(cid=cid).first()
if not user_answer:
# skip if no answer
answers_marks.append(0)
answers.append("")
answer_score = 0
ans = "Not answered"
else:
ans = user_answer.answer
answer_score = user_answer.get_answer_score()
correct_answer = q.GetPrimaryAnswer()
if not exam.publish_results:
correct_answer = "*****"
answer_score = 0
answers.append(ans)
answers_marks.append(answer_score)
answers_and_marks.append((ans, answer_score, correct_answer))
if "unmarked" in answers_marks:
answered = [i for i in answers_marks if type(i) == int]
total_score = sum(answered)
unmarked_number = len(answers_marks) - len(answered)
total_score = "{} ({} unmarked)".format(total_score, unmarked_number)
else:
total_score = sum(answers_marks)
max_score = len(questions) * 2
return render(
request,
"anatomy/exam_scores_user.html",
{
"exam": exam,
"cid": cid,
"questions": questions,
"answers": answers,
"answers_marks": answers_marks,
"total_score": total_score,
"max_score": max_score,
"answers_and_marks": answers_and_marks,
},
)
# @login_required
# def exam_scores(request, pk):
# exam = get_object_or_404(Exam, pk=pk)
# questions = exam.exam_questions.all()
# users = (CidUserAnswer.objects.filter(
# question__in=questions).values_list("user").distinct())
# user_answers_and_marks = defaultdict(list)
# user_answers_marks = defaultdict(list)
# user_answers = defaultdict(list)
# user_names = {}
# by_question = defaultdict(list)
# for u in users:
## Convoluted (probably...)
# user_names[u] = User.objects.filter(pk=u[0]).first().get_username()
# for q in questions:
# user_answer = q.user_answers.filter(user__in=u).first()
# if not user_answer:
# user_answers_marks[u].append(0)
# user_answers[u].append("")
# continue
# ans = user_answer.answer
# answer_score = user_answer.get_answer_score()
# user_answers[u].append(ans)
# user_answers_marks[u].append(answer_score)
# user_answers_and_marks[u].append((ans, answer_score))
# by_question[q].append(ans)
# user_scores = {}
# for user in user_answers_marks:
# user_scores[user] = sum(user_answers_marks[user])
# total = len(questions)
# return render(
# request,
# "anatomy/exam_scores.html",
# {
# "exam": exam,
# "questions": questions,
# "by_question": by_question,
# "user_answers": dict(user_answers),
# "user_answers_marks": dict(user_answers_marks),
# "user_scores": user_scores,
# "user_names": user_names,
# "user_answers_and_marks": user_answers_and_marks,
# },
# )
# def cid_scores(request, pk):
# #exam = get_object_or_404(Exam, pk=pk)
#
# # TODO:Need some kind of test for cid
# cid = pk
#
# #questions = exam.exam_questions.all()
# answers = CidUserAnswer.objects.filter(
# cid=cid)
#
#
# if not answers:
# raise Http404("cid not found")
#
# exam_ids = answers.values_list("exam").distinct()
#
# exams = Exam.objects.filter(id__in=exam_ids)
#
#
# return render(
# request,
# "anatomy/cid_scores.html",
# {
# "exams": exams,
# "cid": cid,
# },
# )
class AnatomyQuestionCreateBase(LoginRequiredMixin, CreateView):
model = AnatomyQuestion
form_class = AnatomyQuestionForm
def get_context_data(self, **kwargs):
context = super(AnatomyQuestionCreateBase, self).get_context_data(**kwargs)
if self.request.POST:
context["answer_formset"] = AnswerFormSet(
self.request.POST, self.request.FILES
)
else:
context["answer_formset"] = AnswerFormSet()
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.save()
form.instance.author.add(self.request.user.id)
context = self.get_context_data(form=form)
formset = context["answer_formset"]
if formset.is_valid():
response = super().form_valid(form)
formset.instance = self.object
formset.save()
# If the normal submit button is pressed we save as normal
if "submit" in self.request.POST:
return response
# else we redirect to the clone url
else:
return redirect("anatomy:question_clone", pk=self.object.pk)
else:
return super().form_invalid(form)
@login_required
def question_clone(request, pk):
new_item = get_object_or_404(AnatomyQuestion, pk=pk)
new_item.pk = None # autogen a new pk (item_id)
# new_item.name = "Copy of " + new_item.name #need to change uniques
form = AnatomyQuestion(request.POST or None, instance=new_item)
formset = AnswerFormSet()
if form.is_valid():
form.instance.author.add(request.user.id)
# logger.debug(formset.is_valid())
if formset.is_valid():
response = super().form_valid(form)
formset.instance = obj
formset.save()
return response
else:
return super().form_invalid(form)
context = {
"form": form,
"answer_formset": formset
# other context
}
return render(request, "anatomy/anatomyquestion_form.html", context)
# @login_required
class AnatomyQuestionCreate(AnatomyQuestionCreateBase):
# initial = {'laterality': AnatomyQuestion.NONE}
def get_initial(self):
pass
# # There has to be a better way...
# try:
# s = (i.pk for i in self.request.user.AnatomyQuestion_default.site.all())
# self.initial.update({'site': s})
# except AttributeError:
# pass
# return self.initial
#
# fields = '__all__'
# #fields = [ 'condition' ]
# #initial = {'date_of_death': '05/01/2018'}
# exclude = [ 'created_date', 'published_date' ]
# self.object = form.save(commit=False)
# self.object.save()
# form.instance.author.add(self.request.user.id)
# return super().form_valid(form)
# class AnatomyQuestionUpdate(LoginRequiredMixin, AuthorOrCheckerRequiredMixin,
class AnatomyQuestionUpdate(LoginRequiredMixin, UpdateView):
model = AnatomyQuestion
form_class = AnatomyQuestionForm
def get_context_data(self, **kwargs):
context = super(AnatomyQuestionUpdate, self).get_context_data(**kwargs)
if self.request.POST:
context["answer_formset"] = AnswerUpdateFormSet(
self.request.POST, self.request.FILES, instance=self.object
)
context["answer_formset"].full_clean()
else:
context["answer_formset"] = AnswerUpdateFormSet(instance=self.object)
return context
def form_valid(self, form):
# save exam orders (there must be a better way to do this)
exam_orders = {}
for exam in self.object.exams.all():
exam_orders[exam] = list(exam.exam_questions.all())
print(exam_orders[exam])
self.object = form.save(commit=False)
self.object.save()
form.instance.author.add(self.request.user.id)
context = self.get_context_data(form=form)
formset = context["answer_formset"]
# logger.debug(formset.is_valid())
if formset.is_valid():
response = super().form_valid(form)
formset.instance = self.object
formset.save()
# restore exam orders
for exam in self.object.exams.all():
if exam in exam_orders and self.object in exam_orders[exam]:
print(exam_orders[exam])
exam.exam_questions.set(exam_orders[exam])
exam.save()
return response
else:
return super().form_invalid(form)
class QuestionClone(AnatomyQuestionCreateBase):
"""Clones a existing rapid"""
# fields = '__all__'
# #fields = [ 'condition' ]
# #initial = {'date_of_death': '05/01/2018'}
# exclude = [ 'created_date', 'published_date' ]
def get_initial(self):
# print(self.request)
old_object = get_object_or_404(AnatomyQuestion, pk=self.kwargs["pk"])
initial_data = model_to_dict(old_object, exclude=["id"])
exams = old_object.exams.all().values_list("id", flat=True)
initial_data["exams"] = list(exams)
return initial_data
@login_required
def create_body_part(request):
form = BodyPartForm(request.POST or None)
if form.is_valid():
instance = form.save()
return HttpResponse(
'<script>opener.closePopup(window, "%s", "%s", "#id_body_part");</script>'
% (instance.pk, instance)
)
return render(
request, "anatomy/create_simple.html", {"form": form, "name": "BodyPart"}
)
@csrf_exempt
def get_body_part_id(request):
if request.is_ajax():
body_part_name = request.GET["body_part_name"]
body_part_id = BodyPart.objects.get(name=body_part_name).id
data = {
"body_part_id": body_part_id,
}
return HttpResponse(json.dumps(data), content_type="application/json")
return HttpResponse("/")
@login_required
def create_examination(request):
form = ExaminationForm(request.POST or None)
if form.is_valid():
instance = form.save()
return HttpResponse(
'<script>opener.closePopup(window, "%s", "%s", "#id_examination");</script>'
% (instance.pk, instance)
)
return render(
request, "anatomy/create_simple.html", {"form": form, "name": "Examination"}
)
@csrf_exempt
def get_examination_id(request):
if request.is_ajax():
examination_name = request.GET["examination_name"]
examination_id = Examination.objects.get(name=examination_name).id
data = {
"examination_id": examination_id,
}
return HttpResponse(json.dumps(data), content_type="application/json")
return HttpResponse("/")
@login_required
def create_structure(request):
form = StructureForm(request.POST or None)
if form.is_valid():
instance = form.save()
return HttpResponse(
'<script>opener.closePopup(window, "%s", "%s", "#id_structure");</script>'
% (instance.pk, instance)
)
return render(
request, "anatomy/create_simple.html", {"form": form, "name": "Structure"}
)
@csrf_exempt
def get_structure_id(request):
if request.is_ajax():
structure_name = request.GET["structure_name"]
structure_id = Structure.objects.get(name=structure_name).id
data = {
"structure_id": structure_id,
}
return HttpResponse(json.dumps(data), content_type="application/json")
return HttpResponse("/")
class AnatomyQuestionView(SingleTableMixin, FilterView):
model = AnatomyQuestion
table_class = AnatomyQuestionTable
template_name = "anatomy/anatomy_question_view.html"
filterset_class = AnatomyQuestionFilter
def question_save_annotation(request, pk):
if request.is_ajax() and request.method == "POST":
question = get_object_or_404(AnatomyQuestion, pk=pk)
question.image_annotations = request.POST.get("annotation")
print(question.image_annotations)
question.save()
data = {"status": "success"}
return JsonResponse(data, status=200)
else:
data = {"status": "error"}
return JsonResponse(data, status=400)