Celebrate Excellence in Education: Nominate Outstanding Educators by April 15!
Found this content helpful? Log in or sign up to leave a like!
This one seems like it should be easy, particularly since I'm using Canvas data instead of our SIS data to test it out.
Looking at the API guide, the Canvas Course ID for the path, and User ID for 'enrollment[user_id]' are the only things required. I am also passing a value for 'enrollment[type]': enrollment_type.
Here is what I have:
def enroll(course_id, user_id, role):
api_url = canvas_url + '/v1/courses/' + str(course_id) + '/enrollments'
if role == 'student':
enrollment_type = 'StudentEnrollment'
else:
enrollment_type = 'TeacherEnrollment'
parameters = {
'enrollment[user_id]': str(user_id),
'enrollment[type]': enrollment_type
}
result = requests.post(api_url,headers=header,data=parameters).json()
print(result)
enroll(3270,4325,'student')
When I run this, the result barfs up what appears to be the code for an HTML page. Here is the error I'm getting:
Traceback (most recent call last):
File "enroll_user_in_course.py", line 25, in <module>
enroll(3270, 4325, 'student')
File "enroll_user_in_course.py", line 22, in enroll
result = requests.post(api_url,headers=header,data=parameters).json()
File "models.py", line 917, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: [Errno Expecting value]
Canvas API programming is starting to make me feel mentally deficient! 😵
Solved! Go to Solution.
Hello @MikeBrinkman
It looks like your function has all the necessary parts, which is a great start.
I usually see that error message when I have a typo in the URL that I am sending. I'm not sure what the value of canvas_url is, but if it doesn't end with "/api" that might be the problem. (or if it ends with "/api/" you would also have an issue due to an extra / in the concatenated string)
Another issue that I sometimes see with enrollments is making sure that the course is still open for enrollment. If the course end dates have passed, then you will need to update the course end dates to allow a new user to be enrolled.
Also, you might want to consider using an if-else statement before getting the JSON response to ensure the response was successful. For example, you could do something like the following:
response = requests.post(api_url, headers=header, data=parameters)
if response.ok:
print(response.json())
else:
print(f"ERROR {response.status_code}: {response.reason}")
On a side note, I took the .json() off of my request, and the response code I get from Canvas is 422 (unprocessable entity).
Hello @MikeBrinkman
It looks like your function has all the necessary parts, which is a great start.
I usually see that error message when I have a typo in the URL that I am sending. I'm not sure what the value of canvas_url is, but if it doesn't end with "/api" that might be the problem. (or if it ends with "/api/" you would also have an issue due to an extra / in the concatenated string)
Another issue that I sometimes see with enrollments is making sure that the course is still open for enrollment. If the course end dates have passed, then you will need to update the course end dates to allow a new user to be enrolled.
Also, you might want to consider using an if-else statement before getting the JSON response to ensure the response was successful. For example, you could do something like the following:
response = requests.post(api_url, headers=header, data=parameters)
if response.ok:
print(response.json())
else:
print(f"ERROR {response.status_code}: {response.reason}")
@JamesSekcienski wrote:
Hello @MikeBrinkman
I'm not sure what the value of canvas_url is, but if it doesn't end with "/api" that might be the problem.
Yes, that was the problem. Obvious means overlooked. 😄
I was trying to be too clever & use constants to simplify my code. I accidentally deleted /api from the full URL when editing.
I will also take the suggestion to include the additional error checking. Thanks again!
Glad to hear you have it working now! Using constants is a good idea. I use a constant for the base url too, but I don't include the /api with it. That way I can just copy the format of the URL for the API call directly from the docs and update it with the necessary variables.
To participate in the Instructure Community, you need to sign up or log in:
Sign In