Exclude surveys from quiz resource import
Observed behaviour
Going on the assumption that we do want users to be able to add free response questions in quizzes too, at this time it is possible to add them to a quiz, but it's not possible to save afterwards, with a
400 Bad Requesterror.![]()
Originally posted by @radinamatic in #13599
Expected behaviour
Because survey questions have no 'correct' answer, and in some cases have a 'correct answer' chosen at random for the sake of having one, we should not allow them to be included in quizzes.
Solution
Exclude survey exercises from quiz resource selection in both backend and frontend.
Backend Changes
File: kolibri/core/content/api.py
In the descendants_assessments action (line 931-952), exclude surveys from the assessment count:
from le_utils.constants import modalities
@action(detail=False)
def descendants_assessments(self, request):
ids = self.request.query_params.get("ids", None)
if not ids:
return Response([])
queryset = self.filter_queryset(self.get_queryset())
data = list(
queryset.annotate(
num_assessments=SQSum(
models.ContentNode.objects.filter(
tree_id=OuterRef("tree_id"),
lft__gte=OuterRef("lft"),
lft__lt=OuterRef("rght"),
kind=content_kinds.EXERCISE,
available=True,
)
.exclude(modality=modalities.SURVEY) # Add this line
.values_list(
"assessmentmetadata__number_of_assessments", flat=True
),
field="number_of_assessments",
)
).values("id", "num_assessments")
)
return Response(data)
This ensures topic descendant counts exclude surveys, so the UI shows accurate counts of selectable resources.
Frontend Changes
File: kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/sidePanels/QuizResourceSelection/index.vue
1. Add a filter function (around line 396, before isPracticeQuiz):
const isNotSurvey = item =>
get(item, ['options', 'modality'], false) !== 'SURVEY';
2. Update the useResourceSelection configuration:
Bookmarks annotator (line 414):
bookmarks: {
filters: { kind: ContentNodeKinds.EXERCISE },
annotator: results => results.filter(isNotSurvey).filter(isPracticeQuiz),
},
Search (add annotator at line 446):
search: {
filters: {
kind: ContentNodeKinds.EXERCISE,
contains_quiz: selectPracticeQuiz ? true : null,
},
annotator: results => results.filter(isNotSurvey),
},
Benefits
- Backend: Topic descendant counts accurately reflect selectable resources (excluding surveys)
- Frontend: Surveys are excluded from all quiz resource selection methods (bookmarks, topic tree, search)
- Prevents 400 Bad Request error when trying to save quizzes with survey questions
- Clear UX - incompatible resources are not shown as options
🤖 This issue was updated with resolution details by Claude Code, under supervision, review and final edits by @rtibbles 🤖