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
c4804485
Commit
c4804485
authored
Oct 21, 2014
by
Zia Fazal
Committed by
Jonathan Piacenti
Aug 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ziafazal/api-added-participant-activity-to-metrics: added
active_users and users_enrolled metrics
parent
00008c06
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
31 additions
and
84 deletions
+31
-84
lms/djangoapps/api_manager/courses/tests.py
+10
-4
lms/djangoapps/api_manager/courses/views.py
+21
-80
No files found.
lms/djangoapps/api_manager/courses/tests.py
View file @
c4804485
...
@@ -2095,6 +2095,11 @@ class CoursesApiTests(ModuleStoreTestCase):
...
@@ -2095,6 +2095,11 @@ class CoursesApiTests(ModuleStoreTestCase):
self
.
assertEqual
(
len
(
response
.
data
[
'modules_completed'
]),
5
)
self
.
assertEqual
(
len
(
response
.
data
[
'modules_completed'
]),
5
)
total_modules_completed
=
sum
([
completed
[
1
]
for
completed
in
response
.
data
[
'modules_completed'
]])
total_modules_completed
=
sum
([
completed
[
1
]
for
completed
in
response
.
data
[
'modules_completed'
]])
self
.
assertEqual
(
total_modules_completed
,
4
)
self
.
assertEqual
(
total_modules_completed
,
4
)
self
.
assertEqual
(
len
(
response
.
data
[
'active_users'
]),
5
)
total_active
=
sum
([
active
[
1
]
for
active
in
response
.
data
[
'active_users'
]])
self
.
assertEqual
(
total_active
,
5
)
self
.
assertEqual
(
response
.
data
[
'users_enrolled'
][
0
][
1
],
25
)
# get modules completed for first 5 days
# get modules completed for first 5 days
start_date
=
datetime
.
now
()
.
date
()
+
relativedelta
(
days
=-
USER_COUNT
)
start_date
=
datetime
.
now
()
.
date
()
+
relativedelta
(
days
=-
USER_COUNT
)
...
@@ -2112,7 +2117,7 @@ class CoursesApiTests(ModuleStoreTestCase):
...
@@ -2112,7 +2117,7 @@ class CoursesApiTests(ModuleStoreTestCase):
# metrics with weeks as interval
# metrics with weeks as interval
end_date
=
datetime
.
now
()
.
date
()
end_date
=
datetime
.
now
()
.
date
()
start_date
=
end_date
+
relativedelta
(
days
=-
10
)
start_date
=
end_date
+
relativedelta
(
weeks
=-
2
)
course_metrics_uri
=
'{}/{}/time-series-metrics/?start_date={}&end_date={}&'
\
course_metrics_uri
=
'{}/{}/time-series-metrics/?start_date={}&end_date={}&'
\
'interval=weeks'
.
format
(
self
.
base_courses_uri
,
'interval=weeks'
.
format
(
self
.
base_courses_uri
,
test_course_id
,
test_course_id
,
...
@@ -2121,9 +2126,9 @@ class CoursesApiTests(ModuleStoreTestCase):
...
@@ -2121,9 +2126,9 @@ class CoursesApiTests(ModuleStoreTestCase):
response
=
self
.
do_get
(
course_metrics_uri
)
response
=
self
.
do_get
(
course_metrics_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
len
(
response
.
data
[
'users_not_started'
]),
2
)
self
.
assert
Greater
Equal
(
len
(
response
.
data
[
'users_not_started'
]),
2
)
self
.
assertEqual
(
len
(
response
.
data
[
'users_started'
]),
2
)
self
.
assert
Greater
Equal
(
len
(
response
.
data
[
'users_started'
]),
2
)
self
.
assertEqual
(
len
(
response
.
data
[
'users_completed'
]),
2
)
self
.
assert
Greater
Equal
(
len
(
response
.
data
[
'users_completed'
]),
2
)
# metrics with months as interval
# metrics with months as interval
start_date
=
end_date
+
relativedelta
(
months
=-
3
)
start_date
=
end_date
+
relativedelta
(
months
=-
3
)
...
@@ -2157,6 +2162,7 @@ class CoursesApiTests(ModuleStoreTestCase):
...
@@ -2157,6 +2162,7 @@ class CoursesApiTests(ModuleStoreTestCase):
response
=
self
.
do_get
(
course_metrics_uri
)
response
=
self
.
do_get
(
course_metrics_uri
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
status_code
,
400
)
def
test_course_workgroups_list
(
self
):
def
test_course_workgroups_list
(
self
):
projects_uri
=
self
.
base_projects_uri
projects_uri
=
self
.
base_projects_uri
data
=
{
data
=
{
...
...
lms/djangoapps/api_manager/courses/views.py
View file @
c4804485
...
@@ -5,6 +5,7 @@ import logging
...
@@ -5,6 +5,7 @@ import logging
import
itertools
import
itertools
from
lxml
import
etree
from
lxml
import
etree
from
StringIO
import
StringIO
from
StringIO
import
StringIO
from
dateutil.relativedelta
import
relativedelta
from
django.conf
import
settings
from
django.conf
import
settings
from
django.contrib.auth.models
import
Group
,
User
from
django.contrib.auth.models
import
Group
,
User
...
@@ -1541,80 +1542,6 @@ class CoursesMetrics(SecureAPIView):
...
@@ -1541,80 +1542,6 @@ class CoursesMetrics(SecureAPIView):
data
.
update
(
thread_stats
)
data
.
update
(
thread_stats
)
return
Response
(
data
,
status
=
status
.
HTTP_200_OK
)
return
Response
(
data
,
status
=
status
.
HTTP_200_OK
)
class
CoursesTimeSeriesMetrics
(
SecureAPIView
):
"""
### The CoursesTimeSeriesMetrics view allows clients to retrieve a list of Metrics for the specified Course
in time series format.
- URI: ```/api/courses/{course_id}/time-series-metrics/?start_date={date}&end_date={date}&interval={interval}&organization={organization_id}```
- interval can be `days`, `weeks` or `months`
- GET: Returns a JSON representation with three metrics
{
"users_not_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_completed": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]]
}
- metrics can be filtered by organization by adding organization parameter to GET request
### Use Cases/Notes:
* Example: Display number of users completed, started or not started in a given course for a given time period
"""
def
get
(
self
,
request
,
course_id
):
# pylint: disable=W0613
"""
GET /api/courses/{course_id}/time-series-metrics/
"""
if
not
course_exists
(
request
,
request
.
user
,
course_id
):
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
start
=
request
.
QUERY_PARAMS
.
get
(
'start_date'
,
None
)
end
=
request
.
QUERY_PARAMS
.
get
(
'end_date'
,
None
)
interval
=
request
.
QUERY_PARAMS
.
get
(
'interval'
,
'days'
)
if
not
start
or
not
end
:
return
Response
({
"message"
:
_
(
"Both start_date and end_date parameters are required"
)}
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
if
interval
not
in
[
'days'
,
'weeks'
,
'months'
]:
return
Response
({
"message"
:
_
(
"Interval parameter is not valid. It should be one of these "
"'days', 'weeks', 'months'"
)},
status
=
status
.
HTTP_400_BAD_REQUEST
)
start_dt
=
parse_datetime
(
start
)
end_dt
=
parse_datetime
(
end
)
course_key
=
get_course_key
(
course_id
)
exclude_users
=
_get_aggregate_exclusion_user_ids
(
course_key
)
grade_complete_match_range
=
getattr
(
settings
,
'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE'
,
0.01
)
grades_qs
=
StudentGradebook
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
.
\
exclude
(
user_id__in
=
exclude_users
)
grades_complete_qs
=
grades_qs
.
filter
(
proforma_grade__lte
=
F
(
'grade'
)
+
grade_complete_match_range
,
proforma_grade__gt
=
0
)
enrolled_qs
=
CourseEnrollment
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
.
exclude
(
id__in
=
exclude_users
)
users_started_qs
=
StudentProgress
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
.
exclude
(
user_id__in
=
exclude_users
)
organization
=
request
.
QUERY_PARAMS
.
get
(
'organization'
,
None
)
if
organization
:
enrolled_qs
=
enrolled_qs
.
filter
(
user__organizations
=
organization
)
grades_complete_qs
=
grades_complete_qs
.
filter
(
user__organizations
=
organization
)
users_started_qs
=
users_started_qs
.
filter
(
user__organizations
=
organization
)
total_enrolled
=
enrolled_qs
.
filter
(
created__lt
=
start_dt
)
.
count
()
total_started
=
users_started_qs
.
filter
(
created__lt
=
start_dt
)
.
count
()
enrolled_series
=
get_time_series_data
(
enrolled_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
date_field
=
'created'
,
aggregate
=
Count
(
'id'
))
started_series
=
get_time_series_data
(
users_started_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
date_field
=
'created'
,
aggregate
=
Count
(
'id'
))
completed_series
=
get_time_series_data
(
grades_complete_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
date_field
=
'modified'
,
aggregate
=
Count
(
'id'
))
not_started_series
=
[]
for
enrolled
,
started
in
zip
(
enrolled_series
,
started_series
):
not_started_series
.
append
((
started
[
0
],
(
total_enrolled
+
enrolled
[
1
])
-
(
total_started
+
started
[
1
])))
total_started
+=
started
[
1
]
total_enrolled
+=
enrolled
[
1
]
data
=
{
'users_not_started'
:
not_started_series
,
'users_started'
:
started_series
,
'users_completed'
:
completed_series
}
return
Response
(
data
,
status
=
status
.
HTTP_200_OK
)
class
CoursesTimeSeriesMetrics
(
SecureAPIView
):
class
CoursesTimeSeriesMetrics
(
SecureAPIView
):
"""
"""
...
@@ -1626,7 +1553,10 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
...
@@ -1626,7 +1553,10 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
{
{
"users_not_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_not_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_started": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"users_completed": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]]
"users_completed": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]],
"modules_completed": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]]
"users_enrolled": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]]
"active_users": [[datetime-1, count-1], [datetime-2, count-2], ........ [datetime-n, count-n]]
}
}
- metrics can be filtered by organization by adding organization parameter to GET request
- metrics can be filtered by organization by adding organization parameter to GET request
### Use Cases/Notes:
### Use Cases/Notes:
...
@@ -1659,18 +1589,22 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
...
@@ -1659,18 +1589,22 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
grades_complete_qs
=
grades_qs
.
filter
(
proforma_grade__lte
=
F
(
'grade'
)
+
grade_complete_match_range
,
grades_complete_qs
=
grades_qs
.
filter
(
proforma_grade__lte
=
F
(
'grade'
)
+
grade_complete_match_range
,
proforma_grade__gt
=
0
)
proforma_grade__gt
=
0
)
enrolled_qs
=
CourseEnrollment
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
enrolled_qs
=
CourseEnrollment
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
.
exclude
(
id__in
=
exclude_users
)
.
exclude
(
user_
id__in
=
exclude_users
)
users_started_qs
=
StudentProgressHistory
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
users_started_qs
=
StudentProgressHistory
.
objects
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
.
exclude
(
user_id__in
=
exclude_users
)
.
exclude
(
user_id__in
=
exclude_users
)
modules_completed_qs
=
CourseModuleCompletion
.
get_actual_completions
()
.
filter
(
course_id__exact
=
course_key
,
modules_completed_qs
=
CourseModuleCompletion
.
get_actual_completions
()
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
\
user__is_active
=
True
)
\
.
exclude
(
id__in
=
exclude_users
)
.
exclude
(
user_id__in
=
exclude_users
)
active_users_qs
=
StudentModule
.
objects
.
filter
(
course_id__exact
=
course_key
,
student__is_active
=
True
)
\
.
exclude
(
student_id__in
=
exclude_users
)
organization
=
request
.
QUERY_PARAMS
.
get
(
'organization'
,
None
)
organization
=
request
.
QUERY_PARAMS
.
get
(
'organization'
,
None
)
if
organization
:
if
organization
:
enrolled_qs
=
enrolled_qs
.
filter
(
user__organizations
=
organization
)
enrolled_qs
=
enrolled_qs
.
filter
(
user__organizations
=
organization
)
grades_complete_qs
=
grades_complete_qs
.
filter
(
user__organizations
=
organization
)
grades_complete_qs
=
grades_complete_qs
.
filter
(
user__organizations
=
organization
)
users_started_qs
=
users_started_qs
.
filter
(
user__organizations
=
organization
)
users_started_qs
=
users_started_qs
.
filter
(
user__organizations
=
organization
)
modules_completed_qs
=
modules_completed_qs
.
filter
(
user__organizations
=
organization
)
modules_completed_qs
=
modules_completed_qs
.
filter
(
user__organizations
=
organization
)
active_users_qs
=
active_users_qs
.
filter
(
student__organizations
=
organization
)
total_enrolled
=
enrolled_qs
.
filter
(
created__lt
=
start_dt
)
.
count
()
total_enrolled
=
enrolled_qs
.
filter
(
created__lt
=
start_dt
)
.
count
()
total_started_count
=
users_started_qs
.
filter
(
created__lt
=
start_dt
)
.
aggregate
(
Count
(
'user'
,
distinct
=
True
))
total_started_count
=
users_started_qs
.
filter
(
created__lt
=
start_dt
)
.
aggregate
(
Count
(
'user'
,
distinct
=
True
))
...
@@ -1684,18 +1618,25 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
...
@@ -1684,18 +1618,25 @@ class CoursesTimeSeriesMetrics(SecureAPIView):
date_field
=
'modified'
,
aggregate
=
Count
(
'id'
))
date_field
=
'modified'
,
aggregate
=
Count
(
'id'
))
modules_completed_series
=
get_time_series_data
(
modules_completed_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
modules_completed_series
=
get_time_series_data
(
modules_completed_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
date_field
=
'created'
,
aggregate
=
Count
(
'id'
))
date_field
=
'created'
,
aggregate
=
Count
(
'id'
))
# active users are those who accessed course in last 24 hours
not_started_series
=
[]
start_dt
=
start_dt
+
relativedelta
(
hours
=-
24
)
end_dt
=
end_dt
+
relativedelta
(
hours
=-
24
)
active_users_series
=
get_time_series_data
(
active_users_qs
,
start_dt
,
end_dt
,
interval
=
interval
,
date_field
=
'modified'
,
aggregate
=
Count
(
'student'
,
distinct
=
True
))
not_started_series
,
total_enrolled_series
=
[],
[]
for
enrolled
,
started
in
zip
(
enrolled_series
,
started_series
):
for
enrolled
,
started
in
zip
(
enrolled_series
,
started_series
):
not_started_series
.
append
((
started
[
0
],
(
total_enrolled
+
enrolled
[
1
])
-
(
total_started
+
started
[
1
])))
not_started_series
.
append
((
started
[
0
],
(
total_enrolled
+
enrolled
[
1
])
-
(
total_started
+
started
[
1
])))
total_started
+=
started
[
1
]
total_started
+=
started
[
1
]
total_enrolled
+=
enrolled
[
1
]
total_enrolled
+=
enrolled
[
1
]
total_enrolled_series
.
append
((
started
[
0
],
total_enrolled
))
data
=
{
data
=
{
'users_not_started'
:
not_started_series
,
'users_not_started'
:
not_started_series
,
'users_started'
:
started_series
,
'users_started'
:
started_series
,
'users_completed'
:
completed_series
,
'users_completed'
:
completed_series
,
'modules_completed'
:
modules_completed_series
'modules_completed'
:
modules_completed_series
,
'users_enrolled'
:
total_enrolled_series
,
'active_users'
:
active_users_series
}
}
return
Response
(
data
,
status
=
status
.
HTTP_200_OK
)
return
Response
(
data
,
status
=
status
.
HTTP_200_OK
)
...
...
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