cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
cph2
Community Contributor

Is there a way to get the list of courses sorted in descending order by course id from canvas?

Jump to solution

Hi all, 

I am trying to write a script that lets me associate a blueprint course with all new courses - but only new courses. Does anyone have a suggestion as to how to find the courses by creation date or course id to allow me to identify the new ones?

Thanks!

Labels (1)
1 Solution

Accepted Solutions
pklove
Community Champion

You can do it with the "List active courses in an account" endpoint.  The sort parameter takes undocumented fields, so you can use id.  For example:

    .../api/v1/accounts/1/courses?sort=id&order=desc

Or with created_at:

   .../api/v1/accounts/1/courses?sort=created_at&order=desc

View solution in original post

4 Replies
anthony_harris
Community Participant

Well, it's not the prettiest way to do it, but while I see in the API where we can sort the returned course list with a couple of parameters passed on the request, it looks like you can only sort on a few fields, none of which are the date or the ID.  If someone has more info and shows you can say sort descending in a way that uses the ID, I'd be interested to hear it as well.

In the mean time, here's a Python script that just pulls them all into a hashed array, and sorts the array based on the key, which is the course ID.

#!/usr/bin/python3
###################################################################################
# listcourses.py
# A sample Python script that lists the courses in our Canvas install.
# ajh 2018-08-15
# For this to work you'll need the requests module installed, which isn't part
# of Python Core.  Also, this is written and tested in Python3, I haven't tried
# to see if it works in Python2 and honestly don't much care to.
###################################################################################

# Pull in the module with tools like exit().  (Why is this not in by default?)
import sys

# Pull in the modules that allow the RESTful API access (https), and JSON parsing.
import requests
import json

# Create and initialize a dictionary (hashed array) to hold the courses for sorting
global courselist
courselist = {}

# The token here is the key to accessing things in our Canvas install.  It's a per-user token
# so you'll want to have an admin generate it to get the required access.  To generate one
# you go to Account, Settings, and under Approved Integrations, get a new access token.
# !!Note!! When you generate the token, copy and paste it somewhere!!  You will never see that
# token again, and if you lose it, you'll have to delete it and generate a new one because you
# cannot get the actual token value shown to you ever again.
token = '(fill in you token here)'

# We'll need to pass the token to Canvas using a custom header on the https request, with
# a name of Authorization and a value of the word Bearer, a space, and the token you generated.
headers = {'Authorization': 'Bearer ' + token}

# This is the URL for the API call we want.  You can get the whole list of these, with descriptions
# of the JSON object returned and any parameters you can pass in (also via JSON usually), by logging
# into Canvas and then going to https://(your.canvas.url)/doc/api/live  (there is no link to this
# inside Canvas so you'll have to go directly to that URL).
# Note that we can't just call api/v1/courses, as that only gives the courses for the user whose
# token we're using.  We have to specify accounts plus the main account id (always 1) plus "courses"
# to get all the courses.  If you only want the courses in one of the sub accounts, specify that
# account's id instead of the main account id.
courseurl = 'https://(your.canvas.url)/api/v1/accounts/1/courses'

# Now the meat of the process.  We're going to loop here to get each of the 10-record pages
# the Canvas API will give us in response to our request.
keepgoing = True
while keepgoing:
    #  Make the call to the API URL and pass in our custom header.
    r = requests.get(courseurl, headers=headers)

    # Make sure the call worked, and if not, we want to throw an error.
    if r.status_code != 200:
        print("ERROR: Status code returned={} for {} -- Exiting.\n".format(r.status_code, courseurl))
        sys.exit()

    # Since there are a lot of these, we'll need to paginate.  That means getting the link
    # header to the next page out of the LINK header.  If there isn't one, then this is the
    # last page.
    linkheader = r.headers['Link']
    # The header has an array of links, separated by commas...
    linklist = linkheader.split(",")
    # Loop through.  We're looking for the "next" link, if there is one...
    nexturl = None
    for linkitem in linklist:
        # Each link item is really two things, the actual URL, and a rel= that tells us what the link is to...
        onelink = linkitem.split(";")
        # If we have a next...
        # Otherwise, if no next, empty nexturl so we'll know.
        if "next" in onelink[1]:
            # Get it, strip the first character (a "<") and the last letter (a ">").
            nexturl = onelink[0]
            nexturl = nexturl[1:]
            nexturl = nexturl[:-1]
    # End of for loop
        
    # Now we pull the text of the response we got back, run that through the JSON decoder, and
    # stuff the whole data structure into a variable.
    data = json.loads(r.text)

    # The response will have an array of records each of which is a hash array with a bunch of items.
    # For this example, we'll cycle through the array, and for each one, get the idnumber and the course name
    # and stick them in a dictionary (a Python hashed array)
    for course in data:
        courselist[course['id']] = course['name']

    # Now, if the nexturl is blank, set the keepgoing flag to false so we'll drop out of the loop.
    # Otherwise, set url to nexturl and we'll get the next page worth.
    if nexturl:
        url = nexturl
    else:
        keepgoing = False

    # End of while loop

# Ok, we've got them all now.  Sort them in descending order by the key and print them out.
for crsid in sorted(courselist, reverse=True):
    print("{} - {}".format(crsid, courselist[crsid]))

# End of sample script.

cph2
Community Contributor

Thanks! I was building a similar php script but I am always appreciative of the support of this community. 

pklove
Community Champion

You can do it with the "List active courses in an account" endpoint.  The sort parameter takes undocumented fields, so you can use id.  For example:

    .../api/v1/accounts/1/courses?sort=id&order=desc

Or with created_at:

   .../api/v1/accounts/1/courses?sort=created_at&order=desc

View solution in original post

cph2
Community Contributor

Thank you! That is exactly what I needed!