Skip to content

[QTI] Allow API endpoint to handle AssessmentItem.raw_data to store QTI data #5999

Description

@rtibbles

This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Overview

Store and round-trip the editor's authored QTI XML on AssessmentItem (type='QTI', full item XML in raw_data) through the save, sync, and internal API paths without altering it.

Complexity: Medium
Target branch: unstable

Context

  • AssessmentItem (contentcuration/contentcuration/models.py) holds type, question, answers, hints, raw_data. type choices are migration-defined (0152, 0154).
  • The endpoint already exists: AssessmentItemViewSet + AssessmentItemSerializer (viewsets/assessmentitem.py), registered in the sync API (viewsets/sync/base.py). This task extends them — not a new endpoint. Type validation already exists (Add validation for the "type" of AssessmentItem objects #4877).
  • Legacy items use structured question/answers; raw_data today carries raw Perseus JSON for perseus_question.
  • For QTI items the full item XML lives in raw_data; question/answers are unused, and the serializer's answers/hints coercion must be bypassed.
  • Nested-resource extraction today is markdown-only: AssessmentItemSerializer.set_files + get_filenames_from_assessment (viewsets/assessmentitem.py) scan question/answers/hints for ![...]($CONTENT_STORAGE/<checksum>.<ext>) and create/claim File rows (preset EXERCISE_IMAGE). QTI items carry references in XML attributes, so that scan finds nothing.
  • Sync is field-level last-write-wins over the single raw_data string.
  • Saves process asynchronously; validation errors return through the sync error channel, not synchronously.

The Change

  • Accept QTI as a valid AssessmentItem.type everywhere the backend enumerates or validates types.
  • Persist and return raw_data verbatim for QTI items through save and sync.
  • Apply no markdown/answer transformation to QTI items.
  • Extract referenced files from the QTI raw_data XML — checksums from src, srcset, href, and data attributes — and create/claim/delete File rows through the existing set_files flow.
  • Validate raw_data against the QTI schema (Ant's backend plus setting up front end files #2) during async sync processing; reject invalid items.

Acceptance Criteria

  • QTI is an accepted AssessmentItem.type across model, validation, and serializers
  • A QTI item's raw_data round-trips byte-for-byte through save and sync
  • No markdown/answer transformation is applied to type='QTI' items
  • Files referenced in a QTI item's raw_data (via src/srcset/href/data) are linked as File rows through the existing claim/create/delete flow
  • Invalid QTI is rejected on save and surfaced to the client
  • Legacy item types save and sync unchanged
  • Tests cover create/update/read and file extraction for a QTI item via the sync API, asserting verbatim round-trip

References

AI usage

Architecture decided with the maintainer across an iterative session: blanket QTI type with the item XML in raw_data; XSD-authoritative validation across all sources; a legacy→QTI global migration with an API-layer dual-read; ricecooker upload delegating to the AssessmentItem serializer; and a Perseus custom-interaction contract confirmed against the QTI 3.0 specification. Claude mapped the existing publish/validation/ricecooker code, proposed the breakdown, and drafted each issue; the maintainer steered every decision and reviewed throughout.

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Task.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions