diff --git a/anatomy/templates/anatomy/partials/exam_edit_fragment.html b/anatomy/templates/anatomy/partials/exam_edit_fragment.html
new file mode 100644
index 00000000..5f1e4435
--- /dev/null
+++ b/anatomy/templates/anatomy/partials/exam_edit_fragment.html
@@ -0,0 +1,23 @@
+{% load static %}
+
+
+
Current exams:
+ {% for exam in question.exams.all %}
+
+ {% empty %}
+ No exams
+ {% endfor %}
+
+
diff --git a/anatomy/views.py b/anatomy/views.py
index 436f6051..eec8d58d 100644
--- a/anatomy/views.py
+++ b/anatomy/views.py
@@ -59,6 +59,21 @@ from .models import (
# HalfMarkAnswers,
# IncorrectAnswers,
)
+from generic.widgets import ExamSearchWidget
+
+
+class AddExamForm(forms.Form):
+ exam = forms.ModelChoiceField(queryset=Exam.objects.none(), required=True, widget=ExamSearchWidget(exam_model=Exam), label="Exam to add")
+
+ def __init__(self, *args, user=None, **kwargs):
+ super().__init__(*args, **kwargs)
+ if user is None:
+ qs = Exam.objects.none()
+ elif user.groups.filter(name="anatomy_checker").exists():
+ qs = Exam.objects.all()
+ else:
+ qs = Exam.objects.filter(author__id=user.id) | Exam.objects.filter(open_access=True)
+ self.fields["exam"].queryset = qs.distinct()
from generic.models import CidUser, Examination
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamGroupsUpdateBase, ExamUpdateBase, ExamViews, GenericViewBase, UpdateQuestionMixin
from reversion.views import RevisionMixin
@@ -1627,44 +1642,39 @@ def question_add_exam(request, question_id: int):
return HttpResponse("Invalid permissions", status=403)
- if request.POST:
+ # POST: handle add/remove; if exam_id provided use existing behaviour
+ if request.method == "POST":
exam_id = request.POST.get("exam_id", None)
- if exam_id is None:
- return HttpResponse("No exam id provided", status=400)
+ if exam_id:
+ exam = get_object_or_404(Exam, pk=exam_id)
+ if request.POST.get("remove", False) == "true":
+ question.exams.remove(exam)
+ else:
+ question.exams.add(exam)
- exam = get_object_or_404(Exam, pk=exam_id)
+ # return updated fragment
+ form = AddExamForm(user=request.user)
+ return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
- if request.POST.get("remove", False) == "true":
- question.exams.remove(exam)
- return HttpResponse("Question removed from exam.")
+ # else try to process from the search form
+ form = AddExamForm(request.POST, user=request.user)
+ if form.is_valid():
+ exam = form.cleaned_data.get("exam")
+ if request.POST.get("remove", False) == "true":
+ question.exams.remove(exam)
+ else:
+ question.exams.add(exam)
+
+ form = AddExamForm(user=request.user)
+ return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
else:
- question.exams.add(exam)
+ # render form with errors
+ return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
- return HttpResponse("Question added to exam.")
- else:
- # Return a list of exams that we can add to the question
-
- exams = Exam.objects.filter(author=request.user)
- exams = exams.difference(question.exams.all())
-
- if not exams:
- return HttpResponse("No exams available to add")
-
- html = "Exams to add to question:
"
- for exam in exams:
- html = html + (f""
- )
- html = html + "
Exams to remove from question:
"
- for exam in question.exams.all():
- html = html + (f""
- )
- html = html + ""
-
- return HttpResponse(mark_safe(html))
+ # GET: render the fragment with the add form and current exams
+ form = AddExamForm(user=request.user)
+ return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
raise PermissionDenied()