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
4b9434a3
Commit
4b9434a3
authored
Jan 27, 2015
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mobile UserCourseStatus API: performance improvement with depth=2.
parent
1840fe7f
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
68 additions
and
45 deletions
+68
-45
lms/djangoapps/mobile_api/users/tests.py
+59
-35
lms/djangoapps/mobile_api/users/views.py
+9
-10
No files found.
lms/djangoapps/mobile_api/users/tests.py
View file @
4b9434a3
...
@@ -90,23 +90,32 @@ class CourseStatusAPITestCase(MobileAPITestCase):
...
@@ -90,23 +90,32 @@ class CourseStatusAPITestCase(MobileAPITestCase):
"""
"""
REVERSE_INFO
=
{
'name'
:
'user-course-status'
,
'params'
:
[
'username'
,
'course_id'
]}
REVERSE_INFO
=
{
'name'
:
'user-course-status'
,
'params'
:
[
'username'
,
'course_id'
]}
def
_setup_course_skeleton
(
self
):
def
setUp
(
self
):
"""
"""
Creates a basic course structure for our course
Creates a basic course structure for our course
"""
"""
section
=
ItemFactory
.
create
(
super
(
CourseStatusAPITestCase
,
self
)
.
setUp
()
parent_location
=
self
.
course
.
location
,
self
.
section
=
ItemFactory
.
create
(
parent
=
self
.
course
,
category
=
'chapter'
,
)
self
.
sub_section
=
ItemFactory
.
create
(
parent
=
self
.
section
,
category
=
'sequential'
,
)
)
sub_section
=
ItemFactory
.
create
(
self
.
unit
=
ItemFactory
.
create
(
parent_location
=
section
.
location
,
parent
=
self
.
sub_section
,
category
=
'vertical'
,
)
)
unit
=
ItemFactory
.
create
(
self
.
other_sub_section
=
ItemFactory
.
create
(
parent_location
=
sub_section
.
location
,
parent
=
self
.
section
,
category
=
'sequential'
,
)
)
other_unit
=
ItemFactory
.
create
(
self
.
other_unit
=
ItemFactory
.
create
(
parent_location
=
sub_section
.
location
,
parent
=
self
.
other_sub_section
,
category
=
'vertical'
,
)
)
return
section
,
sub_section
,
unit
,
other_unit
class
TestCourseStatusGET
(
CourseStatusAPITestCase
,
MobileAuthUserTestMixin
,
MobileEnrolledCourseAccessTestMixin
):
class
TestCourseStatusGET
(
CourseStatusAPITestCase
,
MobileAuthUserTestMixin
,
MobileEnrolledCourseAccessTestMixin
):
...
@@ -115,13 +124,15 @@ class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mobi
...
@@ -115,13 +124,15 @@ class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mobi
"""
"""
def
test_success
(
self
):
def
test_success
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
section
,
sub_section
,
unit
,
__
)
=
self
.
_setup_course_skeleton
()
response
=
self
.
api_response
()
response
=
self
.
api_response
()
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
unicode
(
unit
.
location
))
self
.
assertEqual
(
self
.
assertEqual
(
response
.
data
[
"last_visited_module_path"
],
response
.
data
[
"last_visited_module_id"
],
# pylint: disable=no-member
[
unicode
(
module
.
location
)
for
module
in
[
unit
,
sub_section
,
section
,
self
.
course
]]
unicode
(
self
.
sub_section
.
location
)
)
self
.
assertEqual
(
response
.
data
[
"last_visited_module_path"
],
# pylint: disable=no-member
[
unicode
(
module
.
location
)
for
module
in
[
self
.
sub_section
,
self
.
section
,
self
.
course
]]
)
)
...
@@ -135,37 +146,45 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
...
@@ -135,37 +146,45 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
def
test_success
(
self
):
def
test_success
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
__
,
__
,
__
,
other_unit
)
=
self
.
_setup_course_skeleton
()
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
unicode
(
self
.
other_unit
.
location
)})
self
.
assertEqual
(
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
unicode
(
other_unit
.
location
)})
response
.
data
[
"last_visited_module_id"
],
# pylint: disable=no-member
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
unicode
(
other_unit
.
location
))
unicode
(
self
.
other_sub_section
.
location
)
)
def
test_invalid_module
(
self
):
def
test_invalid_module
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
"abc"
},
expected_response_code
=
400
)
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
"abc"
},
expected_response_code
=
400
)
self
.
assertEqual
(
response
.
data
,
errors
.
ERROR_INVALID_MODULE_ID
)
self
.
assertEqual
(
response
.
data
,
# pylint: disable=no-member
errors
.
ERROR_INVALID_MODULE_ID
)
def
test_nonexistent_module
(
self
):
def
test_nonexistent_module
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
non_existent_key
=
self
.
course
.
id
.
make_usage_key
(
'video'
,
'non-existent'
)
non_existent_key
=
self
.
course
.
id
.
make_usage_key
(
'video'
,
'non-existent'
)
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
non_existent_key
},
expected_response_code
=
400
)
response
=
self
.
api_response
(
data
=
{
"last_visited_module_id"
:
non_existent_key
},
expected_response_code
=
400
)
self
.
assertEqual
(
response
.
data
,
errors
.
ERROR_INVALID_MODULE_ID
)
self
.
assertEqual
(
response
.
data
,
# pylint: disable=no-member
errors
.
ERROR_INVALID_MODULE_ID
)
def
test_no_timezone
(
self
):
def
test_no_timezone
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
__
,
__
,
__
,
other_unit
)
=
self
.
_setup_course_skeleton
()
past_date
=
datetime
.
datetime
.
now
()
past_date
=
datetime
.
datetime
.
now
()
response
=
self
.
api_response
(
response
=
self
.
api_response
(
data
=
{
data
=
{
"last_visited_module_id"
:
unicode
(
other_unit
.
location
),
"last_visited_module_id"
:
unicode
(
self
.
other_unit
.
location
),
"modification_date"
:
past_date
.
isoformat
()
# pylint: disable=maybe-no-member
"modification_date"
:
past_date
.
isoformat
()
# pylint: disable=maybe-no-member
},
},
expected_response_code
=
400
expected_response_code
=
400
)
)
self
.
assertEqual
(
response
.
data
,
errors
.
ERROR_INVALID_MODIFICATION_DATE
)
self
.
assertEqual
(
response
.
data
,
# pylint: disable=no-member
errors
.
ERROR_INVALID_MODIFICATION_DATE
)
def
_date_sync
(
self
,
date
,
initial_unit
,
update_unit
,
expected_
unit
):
def
_date_sync
(
self
,
date
,
initial_unit
,
update_unit
,
expected_
subsection
):
"""
"""
Helper for test cases that use a modification to decide whether
Helper for test cases that use a modification to decide whether
to update the course status
to update the course status
...
@@ -182,36 +201,41 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
...
@@ -182,36 +201,41 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
"modification_date"
:
date
.
isoformat
()
"modification_date"
:
date
.
isoformat
()
}
}
)
)
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
unicode
(
expected_unit
.
location
))
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
# pylint: disable=no-member
unicode
(
expected_subsection
.
location
)
)
def
test_old_date
(
self
):
def
test_old_date
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
__
,
__
,
unit
,
other_unit
)
=
self
.
_setup_course_skeleton
()
date
=
timezone
.
now
()
+
datetime
.
timedelta
(
days
=-
100
)
date
=
timezone
.
now
()
+
datetime
.
timedelta
(
days
=-
100
)
self
.
_date_sync
(
date
,
unit
,
other_unit
,
unit
)
self
.
_date_sync
(
date
,
self
.
unit
,
self
.
other_unit
,
self
.
sub_section
)
def
test_new_date
(
self
):
def
test_new_date
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
__
,
__
,
unit
,
other_unit
)
=
self
.
_setup_course_skeleton
()
date
=
timezone
.
now
()
+
datetime
.
timedelta
(
days
=
100
)
date
=
timezone
.
now
()
+
datetime
.
timedelta
(
days
=
100
)
self
.
_date_sync
(
date
,
unit
,
other_unit
,
other_unit
)
self
.
_date_sync
(
date
,
self
.
unit
,
self
.
other_unit
,
self
.
other_sub_section
)
def
test_no_initial_date
(
self
):
def
test_no_initial_date
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
(
__
,
__
,
_
,
other_unit
)
=
self
.
_setup_course_skeleton
()
response
=
self
.
api_response
(
response
=
self
.
api_response
(
data
=
{
data
=
{
"last_visited_module_id"
:
unicode
(
other_unit
.
location
),
"last_visited_module_id"
:
unicode
(
self
.
other_unit
.
location
),
"modification_date"
:
timezone
.
now
()
.
isoformat
()
"modification_date"
:
timezone
.
now
()
.
isoformat
()
}
}
)
)
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
unicode
(
other_unit
.
location
))
self
.
assertEqual
(
response
.
data
[
"last_visited_module_id"
],
# pylint: disable=no-member
unicode
(
self
.
other_sub_section
.
location
)
)
def
test_invalid_date
(
self
):
def
test_invalid_date
(
self
):
self
.
login_and_enroll
()
self
.
login_and_enroll
()
response
=
self
.
api_response
(
data
=
{
"modification_date"
:
"abc"
},
expected_response_code
=
400
)
response
=
self
.
api_response
(
data
=
{
"modification_date"
:
"abc"
},
expected_response_code
=
400
)
self
.
assertEqual
(
response
.
data
,
errors
.
ERROR_INVALID_MODIFICATION_DATE
)
self
.
assertEqual
(
response
.
data
,
# pylint: disable=no-member
errors
.
ERROR_INVALID_MODIFICATION_DATE
)
class
TestCourseEnrollmentSerializer
(
MobileAPITestCase
):
class
TestCourseEnrollmentSerializer
(
MobileAPITestCase
):
...
...
lms/djangoapps/mobile_api/users/views.py
View file @
4b9434a3
...
@@ -107,15 +107,14 @@ class UserCourseStatus(views.APIView):
...
@@ -107,15 +107,14 @@ class UserCourseStatus(views.APIView):
course
.
id
,
request
.
user
,
course
,
depth
=
2
)
course
.
id
,
request
.
user
,
course
,
depth
=
2
)
course_module
=
get_module_for_descriptor
(
request
.
user
,
request
,
course
,
field_data_cache
,
course
.
id
)
course_module
=
get_module_for_descriptor
(
request
.
user
,
request
,
course
,
field_data_cache
,
course
.
id
)
current
=
course_module
path
=
[]
path
=
[
course_module
]
ch
ild
=
current
ch
apter
=
get_current_child
(
course_module
,
min_depth
=
2
)
while
child
:
if
chapter
is
not
None
:
path
.
append
(
ch
ild
)
path
.
append
(
ch
apter
)
child
=
get_current_child
(
current
)
section
=
get_current_child
(
chapter
,
min_depth
=
1
)
if
child
:
if
section
is
not
None
:
current
=
child
path
.
append
(
section
)
path
.
reverse
()
path
.
reverse
()
return
path
return
path
...
@@ -160,7 +159,7 @@ class UserCourseStatus(views.APIView):
...
@@ -160,7 +159,7 @@ class UserCourseStatus(views.APIView):
save_positions_recursively_up
(
request
.
user
,
request
,
field_data_cache
,
module
)
save_positions_recursively_up
(
request
.
user
,
request
,
field_data_cache
,
module
)
return
self
.
_get_course_info
(
request
,
course
)
return
self
.
_get_course_info
(
request
,
course
)
@mobile_course_access
()
@mobile_course_access
(
depth
=
2
)
def
get
(
self
,
request
,
course
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
def
get
(
self
,
request
,
course
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
"""
"""
Get the ID of the module that the specified user last visited in the specified course.
Get the ID of the module that the specified user last visited in the specified course.
...
@@ -168,7 +167,7 @@ class UserCourseStatus(views.APIView):
...
@@ -168,7 +167,7 @@ class UserCourseStatus(views.APIView):
return
self
.
_get_course_info
(
request
,
course
)
return
self
.
_get_course_info
(
request
,
course
)
@mobile_course_access
()
@mobile_course_access
(
depth
=
2
)
def
patch
(
self
,
request
,
course
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
def
patch
(
self
,
request
,
course
,
*
args
,
**
kwargs
):
# pylint: disable=unused-argument
"""
"""
Update the ID of the module that the specified user last visited in the specified course.
Update the ID of the module that the specified user last visited in the specified course.
...
...
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