Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
796e4cb5
Commit
796e4cb5
authored
9 years ago
by
Ahsan Ulhaq
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8580 from edx/ahsan/ECOM-1719-LMS-Modification-enrollment-API-update
LMS: Modification in enrollment API
parents
a8f909fe
8d9d4b85
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
407 additions
and
11 deletions
+407
-11
common/djangoapps/enrollment/api.py
+53
-2
common/djangoapps/enrollment/data.py
+102
-2
common/djangoapps/enrollment/errors.py
+5
-0
common/djangoapps/enrollment/tests/fake_data_api.py
+19
-0
common/djangoapps/enrollment/tests/test_api.py
+23
-0
common/djangoapps/enrollment/tests/test_data.py
+39
-0
common/djangoapps/enrollment/tests/test_views.py
+75
-1
common/djangoapps/enrollment/views.py
+47
-6
common/djangoapps/student/models.py
+44
-0
No files found.
common/djangoapps/enrollment/api.py
View file @
796e4cb5
...
...
@@ -5,8 +5,8 @@ course level, such as available course modes.
"""
from
django.utils
import
importlib
import
logging
from
django.core.cache
import
cache
from
django.conf
import
settings
from
django.core.cache
import
cache
from
enrollment
import
errors
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -181,7 +181,7 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
return
_data_api
()
.
create_course_enrollment
(
user_id
,
course_id
,
mode
,
is_active
)
def
update_enrollment
(
user_id
,
course_id
,
mode
=
None
,
is_active
=
None
):
def
update_enrollment
(
user_id
,
course_id
,
mode
=
None
,
is_active
=
None
,
enrollment_attributes
=
None
):
"""Updates the course mode for the enrolled user.
Update a course enrollment for the given user and course.
...
...
@@ -232,6 +232,10 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None):
msg
=
u"Course Enrollment not found for user {user} in course {course}"
.
format
(
user
=
user_id
,
course
=
course_id
)
log
.
warn
(
msg
)
raise
errors
.
EnrollmentNotFoundError
(
msg
)
else
:
if
enrollment_attributes
is
not
None
:
set_enrollment_attributes
(
user_id
,
course_id
,
enrollment_attributes
)
return
enrollment
...
...
@@ -302,6 +306,53 @@ def get_course_enrollment_details(course_id, include_expired=False):
return
course_enrollment_details
def
set_enrollment_attributes
(
user_id
,
course_id
,
attributes
):
"""Set enrollment attributes for the enrollment of given user in the
course provided.
Args:
course_id (str): The Course to set enrollment attributes for.
user_id (str): The User to set enrollment attributes for.
attributes (list): Attributes to be set.
Example:
>>>set_enrollment_attributes(
"Bob",
"course-v1-edX-DemoX-1T2015",
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
)
"""
_data_api
()
.
add_or_update_enrollment_attr
(
user_id
,
course_id
,
attributes
)
def
get_enrollment_attributes
(
user_id
,
course_id
):
"""Retrieve enrollment attributes for given user for provided course.
Args:
user_id: The User to get enrollment attributes for
course_id (str): The Course to get enrollment attributes for.
Example:
>>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
Returns: list
"""
return
_data_api
()
.
get_enrollment_attributes
(
user_id
,
course_id
)
def
_validate_course_mode
(
course_id
,
mode
):
"""Checks to see if the specified course mode is valid for the course.
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/data.py
View file @
796e4cb5
...
...
@@ -9,12 +9,12 @@ from opaque_keys.edx.keys import CourseKey
from
xmodule.modulestore.django
import
modulestore
from
enrollment.errors
import
(
CourseNotFoundError
,
CourseEnrollmentClosedError
,
CourseEnrollmentFullError
,
CourseEnrollmentExistsError
,
UserNotFoundError
,
CourseEnrollmentExistsError
,
UserNotFoundError
,
InvalidEnrollmentAttribute
)
from
enrollment.serializers
import
CourseEnrollmentSerializer
,
CourseField
from
student.models
import
(
CourseEnrollment
,
NonExistentCourseError
,
EnrollmentClosedError
,
CourseFullError
,
AlreadyEnrolledError
,
CourseFullError
,
AlreadyEnrolledError
,
CourseEnrollmentAttribute
)
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -136,12 +136,112 @@ def update_course_enrollment(username, course_id, mode=None, is_active=None):
return
None
def
add_or_update_enrollment_attr
(
user_id
,
course_id
,
attributes
):
"""Set enrollment attributes for the enrollment of given user in the
course provided.
Args:
course_id (str): The Course to set enrollment attributes for.
user_id (str): The User to set enrollment attributes for.
attributes (list): Attributes to be set.
Example:
>>>add_or_update_enrollment_attr(
"Bob",
"course-v1-edX-DemoX-1T2015",
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
)
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
user
=
_get_user
(
user_id
)
enrollment
=
CourseEnrollment
.
get_enrollment
(
user
,
course_key
)
if
not
_invalid_attribute
(
attributes
)
and
enrollment
is
not
None
:
CourseEnrollmentAttribute
.
add_enrollment_attr
(
enrollment
,
attributes
)
def
get_enrollment_attributes
(
user_id
,
course_id
):
"""Retrieve enrollment attributes for given user for provided course.
Args:
user_id: The User to get enrollment attributes for
course_id (str): The Course to get enrollment attributes for.
Example:
>>>get_enrollment_attributes("Bob", "course-v1-edX-DemoX-1T2015")
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
Returns: list
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
user
=
_get_user
(
user_id
)
enrollment
=
CourseEnrollment
.
get_enrollment
(
user
,
course_key
)
return
CourseEnrollmentAttribute
.
get_enrollment_attributes
(
enrollment
)
def
_get_user
(
user_id
):
"""Retrieve user with provided user_id
Args:
user_id(str): username of the user for which object is to retrieve
Returns: obj
"""
try
:
return
User
.
objects
.
get
(
username
=
user_id
)
except
User
.
DoesNotExist
:
msg
=
u"Not user with username '{username}' found."
.
format
(
username
=
user_id
)
log
.
warn
(
msg
)
raise
UserNotFoundError
(
msg
)
def
_update_enrollment
(
enrollment
,
is_active
=
None
,
mode
=
None
):
enrollment
.
update_enrollment
(
is_active
=
is_active
,
mode
=
mode
)
enrollment
.
save
()
return
CourseEnrollmentSerializer
(
enrollment
)
.
data
# pylint: disable=no-member
def
_invalid_attribute
(
attributes
):
"""Validate enrollment attribute
Args:
attributes(dict): dict of attribute
Return:
list of invalid attributes
"""
invalid_attributes
=
[]
for
attribute
in
attributes
:
if
"namespace"
not
in
attribute
:
msg
=
u"'namespace' not in enrollment attribute"
log
.
warn
(
msg
)
invalid_attributes
.
append
(
"namespace"
)
raise
InvalidEnrollmentAttribute
(
msg
)
if
"name"
not
in
attribute
:
msg
=
u"'name' not in enrollment attribute"
log
.
warn
(
msg
)
invalid_attributes
.
append
(
"name"
)
raise
InvalidEnrollmentAttribute
(
msg
)
if
"value"
not
in
attribute
:
msg
=
u"'value' not in enrollment attribute"
log
.
warn
(
msg
)
invalid_attributes
.
append
(
"value"
)
raise
InvalidEnrollmentAttribute
(
msg
)
return
invalid_attributes
def
get_course_enrollment_info
(
course_id
,
include_expired
=
False
):
"""Returns all course enrollment information for the given course.
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/errors.py
View file @
796e4cb5
...
...
@@ -50,3 +50,8 @@ class EnrollmentNotFoundError(CourseEnrollmentError):
class
EnrollmentApiLoadError
(
CourseEnrollmentError
):
"""The data API could not be loaded."""
pass
class
InvalidEnrollmentAttribute
(
CourseEnrollmentError
):
"""Enrollment Attributes could not be validated"""
pass
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/tests/fake_data_api.py
View file @
796e4cb5
...
...
@@ -19,6 +19,8 @@ _ENROLLMENTS = []
_COURSES
=
[]
_ENROLLMENT_ATTRIBUTES
=
[]
# pylint: disable=unused-argument
def
get_course_enrollments
(
student_id
):
...
...
@@ -78,6 +80,23 @@ def add_enrollment(student_id, course_id, is_active=True, mode='honor'):
return
enrollment
# pylint: disable=unused-argument
def
add_or_update_enrollment_attr
(
user_id
,
course_id
,
attributes
):
"""Add or update enrollment attribute array"""
for
attribute
in
attributes
:
_ENROLLMENT_ATTRIBUTES
.
append
({
'namespace'
:
attribute
[
'namespace'
],
'name'
:
attribute
[
'name'
],
'value'
:
attribute
[
'value'
]
})
# pylint: disable=unused-argument
def
get_enrollment_attributes
(
user_id
,
course_id
):
"""Retrieve enrollment attribute array"""
return
_ENROLLMENT_ATTRIBUTES
def
add_course
(
course_id
,
enrollment_start
=
None
,
enrollment_end
=
None
,
invite_only
=
False
,
course_modes
=
None
):
"""Append course to the courses array."""
course_info
=
{
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/tests/test_api.py
View file @
796e4cb5
...
...
@@ -143,6 +143,29 @@ class EnrollmentTest(TestCase):
result
=
api
.
update_enrollment
(
self
.
USERNAME
,
self
.
COURSE_ID
,
mode
=
'verified'
)
self
.
assertEquals
(
'verified'
,
result
[
'mode'
])
def
test_update_enrollment_attributes
(
self
):
# Add fake course enrollment information to the fake data API
fake_data_api
.
add_course
(
self
.
COURSE_ID
,
course_modes
=
[
'honor'
,
'verified'
,
'audit'
,
'credit'
])
# Enroll in the course and verify the URL we get sent to
result
=
api
.
add_enrollment
(
self
.
USERNAME
,
self
.
COURSE_ID
,
mode
=
'audit'
)
get_result
=
api
.
get_enrollment
(
self
.
USERNAME
,
self
.
COURSE_ID
)
self
.
assertEquals
(
result
,
get_result
)
enrollment_attributes
=
[
{
"namespace"
:
"credit"
,
"name"
:
"provider_id"
,
"value"
:
"hogwarts"
,
}
]
result
=
api
.
update_enrollment
(
self
.
USERNAME
,
self
.
COURSE_ID
,
mode
=
'credit'
,
enrollment_attributes
=
enrollment_attributes
)
self
.
assertEquals
(
'credit'
,
result
[
'mode'
])
attributes
=
api
.
get_enrollment_attributes
(
self
.
USERNAME
,
self
.
COURSE_ID
)
self
.
assertEquals
(
enrollment_attributes
[
0
],
attributes
[
0
])
def
test_get_course_details
(
self
):
# Add a fake course enrollment information to the fake data API
fake_data_api
.
add_course
(
self
.
COURSE_ID
,
course_modes
=
[
'honor'
,
'verified'
,
'audit'
])
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/tests/test_data.py
View file @
796e4cb5
...
...
@@ -170,6 +170,45 @@ class EnrollmentDataTest(ModuleStoreTestCase):
self
.
assertEqual
(
self
.
user
.
username
,
result
[
'user'
])
self
.
assertEqual
(
enrollment
,
result
)
@ddt.data
(
# Default (no course modes in the database)
# Expect that users are automatically enrolled as "honor".
([],
'credit'
),
# Audit / Verified / Honor
# We should always go to the "choose your course" page.
# We should also be enrolled as "honor" by default.
([
'honor'
,
'verified'
,
'audit'
,
'credit'
],
'credit'
),
)
@ddt.unpack
def
test_add_or_update_enrollment_attr
(
self
,
course_modes
,
enrollment_mode
):
# Create the course modes (if any) required for this test case
self
.
_create_course_modes
(
course_modes
)
data
.
create_course_enrollment
(
self
.
user
.
username
,
unicode
(
self
.
course
.
id
),
enrollment_mode
,
True
)
enrollment_attributes
=
[
{
"namespace"
:
"credit"
,
"name"
:
"provider_id"
,
"value"
:
"hogwarts"
,
}
]
data
.
add_or_update_enrollment_attr
(
self
.
user
.
username
,
unicode
(
self
.
course
.
id
),
enrollment_attributes
)
enrollment_attr
=
data
.
get_enrollment_attributes
(
self
.
user
.
username
,
unicode
(
self
.
course
.
id
))
self
.
assertEqual
(
enrollment_attr
[
0
],
enrollment_attributes
[
0
])
enrollment_attributes
=
[
{
"namespace"
:
"credit"
,
"name"
:
"provider_id"
,
"value"
:
"ASU"
,
}
]
data
.
add_or_update_enrollment_attr
(
self
.
user
.
username
,
unicode
(
self
.
course
.
id
),
enrollment_attributes
)
enrollment_attr
=
data
.
get_enrollment_attributes
(
self
.
user
.
username
,
unicode
(
self
.
course
.
id
))
self
.
assertEqual
(
enrollment_attr
[
0
],
enrollment_attributes
[
0
])
@raises
(
CourseNotFoundError
)
def
test_non_existent_course
(
self
):
data
.
get_course_enrollment_info
(
"this/is/bananas"
)
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/tests/test_views.py
View file @
796e4cb5
...
...
@@ -46,6 +46,7 @@ class EnrollmentTestMixin(object):
as_server
=
False
,
mode
=
CourseMode
.
HONOR
,
is_active
=
None
,
enrollment_attributes
=
None
,
):
"""
Enroll in the course and verify the response's status code. If the expected status is 200, also validates
...
...
@@ -62,7 +63,8 @@ class EnrollmentTestMixin(object):
'course_details'
:
{
'course_id'
:
course_id
},
'user'
:
username
'user'
:
username
,
'enrollment_attributes'
:
enrollment_attributes
}
if
is_active
is
not
None
:
...
...
@@ -547,6 +549,78 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase):
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
VERIFIED
)
def
test_enrollment_with_credit_mode
(
self
):
"""With the right API key, update an existing enrollment with credit
mode and set enrollment attributes.
"""
for
mode
in
[
CourseMode
.
HONOR
,
CourseMode
.
CREDIT_MODE
]:
CourseModeFactory
.
create
(
course_id
=
self
.
course
.
id
,
mode_slug
=
mode
,
mode_display_name
=
mode
,
)
# Create an enrollment
self
.
assert_enrollment_status
(
as_server
=
True
)
# Check that the enrollment is honor.
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
))
course_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
HONOR
)
# Check that the enrollment upgraded to credit.
enrollment_attributes
=
[{
"namespace"
:
"credit"
,
"name"
:
"provider_id"
,
"value"
:
"hogwarts"
,
}]
self
.
assert_enrollment_status
(
as_server
=
True
,
mode
=
CourseMode
.
CREDIT_MODE
,
expected_status
=
status
.
HTTP_200_OK
,
enrollment_attributes
=
enrollment_attributes
)
course_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
CREDIT_MODE
)
def
test_enrollment_with_invalid_attr
(
self
):
"""Check response status is bad request when invalid enrollment
attributes are passed
"""
for
mode
in
[
CourseMode
.
HONOR
,
CourseMode
.
CREDIT_MODE
]:
CourseModeFactory
.
create
(
course_id
=
self
.
course
.
id
,
mode_slug
=
mode
,
mode_display_name
=
mode
,
)
# Create an enrollment
self
.
assert_enrollment_status
(
as_server
=
True
)
# Check that the enrollment is honor.
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
))
course_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
HONOR
)
# Check that the enrollment upgraded to credit.
enrollment_attributes
=
[{
"namespace"
:
"credit"
,
"name"
:
"invalid"
,
"value"
:
"hogwarts"
,
}]
self
.
assert_enrollment_status
(
as_server
=
True
,
mode
=
CourseMode
.
CREDIT_MODE
,
expected_status
=
status
.
HTTP_400_BAD_REQUEST
,
enrollment_attributes
=
enrollment_attributes
)
course_mode
,
is_active
=
CourseEnrollment
.
enrollment_mode_for_user
(
self
.
user
,
self
.
course
.
id
)
self
.
assertTrue
(
is_active
)
self
.
assertEqual
(
course_mode
,
CourseMode
.
HONOR
)
def
test_downgrade_enrollment_with_mode
(
self
):
"""With the right API key, downgrade an existing enrollment with a new mode. """
# Create an honor and verified mode for a course. This allows an update.
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/enrollment/views.py
View file @
796e4cb5
...
...
@@ -5,7 +5,6 @@ consist primarily of authentication, request validation, and serialization.
"""
import
logging
from
ipware.ip
import
get_ip
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.utils.decorators
import
method_decorator
from
opaque_keys
import
InvalidKeyError
...
...
@@ -33,7 +32,11 @@ from enrollment.errors import (
)
from
student.models
import
User
log
=
logging
.
getLogger
(
__name__
)
REQUIRED_ATTRIBUTES
=
{
"credit"
:
[
"credit:provider_id"
],
}
class
EnrollmentCrossDomainSessionAuth
(
SessionAuthenticationAllowInactiveUser
,
SessionAuthenticationCrossDomainCsrf
):
...
...
@@ -264,9 +267,13 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
If honor mode is not supported for the course, the request fails and returns the available modes.
A server-to-server call can be used by this command to enroll a user in other modes, such as "verified"
or "professional". If the mode is not supported for the course, the request will fail and return the
available modes.
A server-to-server call can be used by this command to enroll a user in other modes, such as "verified",
"professional" or "credit". If the mode is not supported for the course, the request will fail and
return the available modes.
You can include other parameters as enrollment attributes for specific course mode as needed. For
example, for credit mode, you can include parameters namespace:'credit', name:'provider_id',
value:'UniversityX' to specify credit provider attribute.
**Example Requests**:
...
...
@@ -274,6 +281,12 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
POST /api/enrollment/v1/enrollment{"mode": "honor", "course_details":{"course_id": "edX/DemoX/Demo_Course"}}
POST /api/enrollment/v1/enrollment{
"mode": "credit",
"course_details":{"course_id": "edX/DemoX/Demo_Course"},
"enrollment_attributes":[{"namespace": "credit","name": "provider_id","value": "hogwarts",},]
}
**Post Parameters**
* user: The username of the currently logged in user. Optional.
...
...
@@ -292,6 +305,12 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
* email_opt_in: A Boolean indicating whether the user
wishes to opt into email from the organization running this course. Optional.
* enrollment_attributes: A list of dictionary that contains:
* namespace: Namespace of the attribute
* name: Name of the attribute
* value: Value of the attribute
**Response Values**
A collection of course enrollments for the user, or for the newly created enrollment.
...
...
@@ -335,7 +354,6 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
* user: The username of the user.
"""
authentication_classes
=
OAuth2AuthenticationAllowInactiveUser
,
EnrollmentCrossDomainSessionAuth
permission_classes
=
ApiKeyHeaderPermissionIsAuthenticated
,
throttle_classes
=
EnrollmentUserThrottle
,
...
...
@@ -370,6 +388,7 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
go through `add_enrollment()`, which allows creation of new and reactivation of old enrollments.
"""
# Get the User, Course ID, and Mode from the request.
username
=
request
.
DATA
.
get
(
'user'
,
request
.
user
.
username
)
course_id
=
request
.
DATA
.
get
(
'course_details'
,
{})
.
get
(
'course_id'
)
...
...
@@ -438,9 +457,17 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
}
)
enrollment_attributes
=
request
.
DATA
.
get
(
'enrollment_attributes'
)
enrollment
=
api
.
get_enrollment
(
username
,
unicode
(
course_id
))
mode_changed
=
enrollment
and
mode
is
not
None
and
enrollment
[
'mode'
]
!=
mode
active_changed
=
enrollment
and
is_active
is
not
None
and
enrollment
[
'is_active'
]
!=
is_active
missing_attrs
=
[]
if
enrollment_attributes
:
actual_attrs
=
[
u"{namespace}:{name}"
.
format
(
**
attr
)
for
attr
in
enrollment_attributes
]
missing_attrs
=
set
(
REQUIRED_ATTRIBUTES
.
get
(
mode
,
[]))
-
set
(
actual_attrs
)
if
has_api_key_permissions
and
(
mode_changed
or
active_changed
):
if
mode_changed
and
active_changed
and
not
is_active
:
# if the requester wanted to deactivate but specified the wrong mode, fail
...
...
@@ -451,7 +478,21 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
)
log
.
warning
(
msg
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"message"
:
msg
})
response
=
api
.
update_enrollment
(
username
,
unicode
(
course_id
),
mode
=
mode
,
is_active
=
is_active
)
if
len
(
missing_attrs
)
>
0
:
msg
=
u"Missing enrollment attributes: requested mode={} required attributes={}"
.
format
(
mode
,
REQUIRED_ATTRIBUTES
.
get
(
mode
)
)
log
.
warning
(
msg
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"message"
:
msg
})
response
=
api
.
update_enrollment
(
username
,
unicode
(
course_id
),
mode
=
mode
,
is_active
=
is_active
,
enrollment_attributes
=
enrollment_attributes
)
else
:
# Will reactivate inactive enrollments.
response
=
api
.
add_enrollment
(
username
,
unicode
(
course_id
),
mode
=
mode
,
is_active
=
is_active
)
...
...
This diff is collapsed.
Click to expand it.
common/djangoapps/student/models.py
View file @
796e4cb5
...
...
@@ -1854,3 +1854,47 @@ class CourseEnrollmentAttribute(models.Model):
name
=
self
.
name
,
value
=
self
.
value
,
)
@classmethod
def
add_enrollment_attr
(
cls
,
enrollment
,
data_list
):
"""Delete all the enrollment attributes for the given enrollment and
add new attributes.
Args:
enrollment(CourseEnrollment): 'CourseEnrollment' for which attribute is to be added
data(list): list of dictionaries containing data to save
"""
cls
.
objects
.
filter
(
enrollment
=
enrollment
)
.
delete
()
attributes
=
[
cls
(
enrollment
=
enrollment
,
namespace
=
data
[
'namespace'
],
name
=
data
[
'name'
],
value
=
data
[
'value'
])
for
data
in
data_list
]
cls
.
objects
.
bulk_create
(
attributes
)
@classmethod
def
get_enrollment_attributes
(
cls
,
enrollment
):
"""Retrieve list of all enrollment attributes.
Args:
enrollment(CourseEnrollment): 'CourseEnrollment' for which list is to retrieve
Returns: list
Example:
>>> CourseEnrollmentAttribute.get_enrollment_attributes(CourseEnrollment)
[
{
"namespace": "credit",
"name": "provider_id",
"value": "hogwarts",
},
]
"""
return
[
{
"namespace"
:
attribute
.
namespace
,
"name"
:
attribute
.
name
,
"value"
:
attribute
.
value
,
}
for
attribute
in
cls
.
objects
.
filter
(
enrollment
=
enrollment
)
]
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment