Hi everyone,
following up on this, I poked around the Git history for two similarly named endpoints in the enrollment app’s REST API, namely
-
api/enrollment/v1/enrollment
, which maps toenrollments.views.EnrollmentListView
:
edx-platform/views.py at master · edx/edx-platform · GitHub -
api/enrollment/v1/enrollments
, which maps toenrollments.views.CourseEnrollmentsApiListView
:
edx-platform/views.py at master · edx/edx-platform · GitHub
Apparently EnrollmentListView
has been accessible via the REST API since 2015 (see PR 7193, submitted by @Diana_Huang and reviewed by Renzo Lucioni), whereas CourseEnrollmentsApiListView
is more recent, from 2019 (PR 18838, submitted by @guruprasad and reviewed by @jill and @dave).
It looks as though the instruction “give me all enrollments of a specific user” can be expressed via a GET
request to either endpoint, namely
api/enrollment/v1/enrollment?user=<username>
api/enrollment/v1/enrollments?username=<username>
These two endpoints behave quite differently if a user at some point enrolled in a course that was subsequently deleted from the CMS:
-
With the
enrollment
URL (using the older view), the deleted courses are simply omitted in the response. This is the behavior that I would intuitively consider “correct”. -
With the
enrollments
URL, we get an HTTP 500, triggered by theCourseEnrollmentsApiListSerializer
class:
Exception Type: AttributeError at /api/enrollment/v1/enrollments
Exception Value: Got AttributeError when attempting to get a value for field `course_id` on serializer `CourseEnrollmentsApiListSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `CourseEnrollment` instance.
Original exception text was: 'NoneType' object has no attribute 'id'.
This appears to come from:
I suppose what this means is that since we don’t have a matching course (that course having been deleted), the course_overview
object reference is None
and hence we get the AttributeError
. I think that the uncaught error might be fixed by simply adding required=False
to the kwargs for CharField
— but I’m by no means a DRF expert, so please take this with a big pinch of salt.
But I’d really like to understand the respective purposes of the enrollment
and enrollments
endpoints in the first place. Is one of them preferred over the other? Is or was one of them meant to replace the other at some point?
And also, is my assessment of what’s causing the HTTP 500 correct?
Thanks in advance for your thoughts!