Skip to content

Instantly share code, notes, and snippets.

@stevenbell
Created October 14, 2022 18:07
Show Gist options
  • Save stevenbell/80d5f14b608e3392c068e822da48566d to your computer and use it in GitHub Desktop.
Save stevenbell/80d5f14b608e3392c068e822da48566d to your computer and use it in GitHub Desktop.
Push a QTI file to canvas and configure some basic settings of the uploaded quiz
#! /bin/python3
# Push a QTI file to Canvas and configure the settings of the resulting imported quiz
# This code is public domain.
# Steven Bell <[email protected]>
from canvasapi import Canvas
import requests
from sys import argv
from time import sleep
from IPython import embed
API_URL = 'YOUR CANVAS API URL'
API_KEY = 'YOUR CANVAS API KEY'
COURSE_ID = 12345 # YOUR COURSE ID NUMBER
if len(argv) != 2:
print("USAGE: push QTI.ZIP\n")
exit()
qtifile = argv[1]
# Initiate the conversion; the response will contain the URL to POST our file to
payload = {"migration_type":"qti_converter", "pre_attachment[name]":qtifile}
response = requests.post(f"{API_URL}/api/v1/courses/{COURSE_ID}/content_migrations/", params=payload, headers={"Authorization":"Bearer " + API_KEY})
blob = response.json()
migration_id = blob["id"]
upload_url = blob["pre_attachment"]["upload_url"]
upload_params = blob["pre_attachment"]["upload_params"]
progress_url = blob["progress_url"]
# Now upload the file itself
r = requests.post(upload_url, params=upload_params, files={"file:":open(qtifile, "rb")})
# Finally, confirm the upload to initiate the conversion process
#r2 = requests.get(f"{API_URL}/api/v1/courses/{COURSE_ID}/content_migrations/{importid}/", headers={"Authorization":"Bearer " + API_KEY})
# We can do the rest with the canvasapi Python library, so switch over now
canvas = Canvas(API_URL, API_KEY)
course = canvas.get_course(COURSE_ID)
# Check the progress of the import and wait until it's finished
# For debugging, it's possible to view the status on Canvas:
# https://canvas.tufts.edu/courses/40488/content_migrations
quizimport = course.get_content_migration(migration_id)
progress = quizimport.get_progress()
while progress.workflow_state != "completed":
print(f"\rWaiting for processing: {progress.workflow_state} | {progress.completion}% complete")
sleep(1)
progress = quizimport.get_progress()
print("Import completed!")
sleep(1) # Wait a second to make sure the quiz appears before we go looking for it
# Find the newly-created quiz
# Sometimes the quiz contains a link to the migration ID, so try that first
newquiz = None
newestId = 0
for q in course.get_quizzes():
if q.id > newestId:
newestId = q.id
if type(q.migration_id) is str and q.migration_id.startswith(f"{migration_id}_"):
print(f"Found imported quiz ({q.title}); configuring it")
newquiz = q
break
if newquiz is None:
newquiz = course.get_quiz(newestId)
print(f"Imported quiz not positively identified; using newest quiz ({newquiz.title})")
quizconfig = {
# "shuffle_answers": True,
"allowed_attempts": 3,
"hide_results": None,
"show_correct_answers": False,
"published": True
}
newquiz = newquiz.edit(quiz=quizconfig)
print("Quiz configured and published!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment