Cumulative Team Journals: Converting Quiz answers to Canvas pages using the Canvas Python API

bob_elliott
Community Explorer

I am posting this code, in case it might be helpful to someone else.

I run an online robotics program. I am a Canvas instructor.

One major component of assessment is the weekly team journal. Because the students don't have the skills yet to write a detailed journal unassisted, I give them guiding questions, in the form of a weekly Canvas quiz: What did you work on, what did you achieve, what problems, what solutions, what learning, what next week, and document using photo, video, code or screenshot.

I have three goals: accountability, feedback, and helping the students accumulate a record of what they did, so at the end of the year they have a resource to make a portfolio (they forget a lot of what they achieved and the problems they overcame.

Here is the code I wrote that converts the Canvas quiz answers into a Canvas page for

# ConcatenateJournalAnswers.py
#
# This program takes the weekly team answers to a journal (a quiz in the Canvas LMS) and then sorts them and posts their answers to a team Canvas page that accumlates each teams's weekly journal answers. At the end of the year the students will have a convenient summary of their work and a quick place to look for resources and ideas to put in their portfolio.

# https://readthedocs.org/projects/canvasapi/downloads/pdf/latest/
# https://github.com/ucfopen/canvasapi
# https://canvas.education.tas.gov.au/doc/api/live#!/

# https://community.canvaslms.com/t5/Developers-Group/Canvas-APIs-Getting-started-the-practical-ins-an...


import csv
from canvasapi import Canvas

API_URL = "https://canvas.education.tas.gov.au/api/v1/"
API_KEY = "IHaveREmovedTheREalKey"

canvas = Canvas(API_URL,API_KEY)
course=canvas.get_course(50818)

print(course.name)

# Create an empty lookup table for a team member's group
group_dict = {
}

# Stores the cummulative text for body of each group's wiki page in body_dict[group.id] = { }
# I realise it would be more efficient to read the group's existing page and add the new quiz to it, but.... that requires some bookkeeping to know what has been added and what has not. This method is slower and less efficient, but more reliable.

# Populate the group lookup table and initialize the body (string) of the wiki page for each group.
groups = course.get_groups()
for group in groups:
print(group)
body_dict[group.id] = "<p>End of team journal</p>"
g_users = group.get_users()
for g_user in g_users:
group_dict[g_user.id] = group.id

# Retrieve the quiz submissions
# Under the hood pagination prevents sorting this list directly quizzes = course.get_quizzes()

# create and populate a local sortable index list index_tuples = []
ctr=0
for quiz in quizzes:
start_stop_dates = quiz.all_dates[0]
if start_stop_dates["unlock_at"] == None:
date_tuple = ("0000", ctr)
else:
date_tuple = (start_stop_dates["unlock_at"], ctr)
index_tuples.append(date_tuple)
ctr += 1


# Process the quizzes in order by date
index_tuples.sort()
for index in index_tuples:
quiz = quizzes[index[1]]
if "journal"or "Journal" in quiz.title:
print(quiz)
question_count = quiz.question_count
questions = quiz.get_questions()
#print(len(questions)) - won't work because paginated list has no length

#Get the submissions for each quiz
submissions = quiz.get_submissions()
for submission in submissions:
# if submission.id == 106865: # only here to facilitate debugging
if True: # only here to facilitate debugging

# Open the quiz report file, find the line matching this submission, and extract the answers to a list
try:
file_name_string = "./csv_id/" + str(quiz.id) + ".csv"
print(file_name_string)

# The next line should open file_name_string, but does not, unless I copy and paste in the console output of the previous line
with open(file_name_string) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
line_count = 0
for row in csv_reader:
if line_count == 0:
line_count += 1
else:
# check we have the correct row of answers
if submission.user_id == int(row[1]):
# print(f'\t{row[0]}') this is the name of the submitter

# Populate list containing the local copy of the teams answers
answers = []
question_ctr=1
while question_ctr <= question_count:
answers.append(row[2*question_ctr+6])
question_ctr += 1
line_count += 1
print(answers)
except:
print("Failed opening file" + file_name_string)

# Add the answers and questions to the string containing the web page body
try:
group = group_dict[submission.user_id]
i = question_count - 1
while i >= 0 :
body_dict[group] = "<p>" + answers[i] + "</p>" + "\n" + body_dict[group]
body_dict[group] = "<h4>" + questions[i].question_name + "</h4>" + "\n" + body_dict[group]
i -= 1
body_dict[group] = "<h3>" + str(quiz) + "</h3>" + "\n" + body_dict[group]
print(submission)
except:
print("Could not find user in groups: " + str(submission.user_id))

# Post the string containing the page body to the team's Canvas journal page for team_id in body_dict:
if team_id == 4214: # only here to facilitate debugging - remove so that it makes pages for all the teams
try:
team = canvas.get_group(team_id)
group_page = course.get_page("Journal " + str(team))
group_page.edit(wiki_page = {'body': body_dict[team_id] })
except:
group_page = course.create_page({'title': "Journal " + str(team), 'body': body_dict[team_id]})
print(str(group) + " journal page created")

Labels (1)