diff --git a/quiz/forms.py b/quiz/forms.py index b3d3a11..4bbbced 100644 --- a/quiz/forms.py +++ b/quiz/forms.py @@ -59,11 +59,41 @@ class MCQuestionForm(forms.ModelForm): model = MCQuestion exclude = () +class MCQuestionFormSet(forms.BaseInlineFormSet): + def clean(self): + """ + Custom validation for the formset to ensure: + 1. At least two choices are provided and not marked for deletion. + 2. At least one of the choices is marked as correct. + """ + super().clean() + + # Collect non-deleted forms + valid_forms = [form for form in self.forms if not form.cleaned_data.get('DELETE', True)] + + valid_choices = ['choice' in form.cleaned_data.keys() for form in valid_forms] + if(not all(valid_choices)): + raise forms.ValidationError("You must add a valid choice name.") + + # If all forms are deleted, raise a validation error + if len(valid_forms) < 2: + raise forms.ValidationError("You must provide at least two choices.") + + # Check if at least one of the valid forms is marked as correct + correct_choices = [form.cleaned_data.get('correct', False) for form in valid_forms] + + if not any(correct_choices): + raise forms.ValidationError("One choice must be marked as correct.") + + if correct_choices.count(True)>1: + raise forms.ValidationError("Only one choice must be marked as correct.") + MCQuestionFormSet = inlineformset_factory( MCQuestion, Choice, form=MCQuestionForm, + formset=MCQuestionFormSet, fields=["choice", "correct"], can_delete=True, extra=5, diff --git a/quiz/views.py b/quiz/views.py index 0ea05bd..da1a678 100644 --- a/quiz/views.py +++ b/quiz/views.py @@ -118,10 +118,10 @@ class MCQuestionCreate(CreateView): context = self.get_context_data() formset = context["formset"] course = context["course"] - with transaction.atomic(): - form.instance.question = self.request.POST.get("content") - self.object = form.save() - if formset.is_valid(): + if formset.is_valid(): + with transaction.atomic(): + form.instance.question = self.request.POST.get("content") + self.object = form.save() formset.instance = self.object formset.save() if "another" in self.request.POST: @@ -131,6 +131,8 @@ class MCQuestionCreate(CreateView): quiz_id=self.kwargs["quiz_id"], ) return redirect("quiz_index", course.slug) + else: + return self.form_invalid(form) return super(MCQuestionCreate, self).form_invalid(form) diff --git a/templates/quiz/mcquestion_form.html b/templates/quiz/mcquestion_form.html index ae9f809..7cae6a7 100644 --- a/templates/quiz/mcquestion_form.html +++ b/templates/quiz/mcquestion_form.html @@ -14,8 +14,17 @@ -
Add questions [{{ quiz_obj|truncatechars:15 }}]
-

+
Add questions [{{ quiz_obj|truncatechars:15 }}]
+ +{% if formset.non_form_errors %} +
+ +
+{% endif %}
{{ quizQuestions }} question added
@@ -40,11 +49,11 @@
- {{ fs.correct }} Correct + {{ fs.correct }} Correct
{{ fs.choice }}
- {{ fs.DELETE }} Delete + {{ fs.DELETE }} Delete
{% endfor %} diff --git a/templates/quiz/quiz_list.html b/templates/quiz/quiz_list.html index 283111b..326f337 100644 --- a/templates/quiz/quiz_list.html +++ b/templates/quiz/quiz_list.html @@ -72,6 +72,11 @@
+ + {% empty %} +

+ Course quizzes will appear here. +

{% endfor %}