Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-analytics-data-api
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-analytics-data-api
Commits
e72a5629
Commit
e72a5629
authored
May 24, 2017
by
Eric Fischer
Committed by
GitHub
May 24, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add passing_users to course summary (#170)
EDU-153
parent
5a85c451
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
25 additions
and
4 deletions
+25
-4
AUTHORS
+1
-0
analytics_data_api/management/commands/generate_fake_course_data.py
+4
-2
analytics_data_api/v0/models.py
+1
-0
analytics_data_api/v0/serializers.py
+1
-0
analytics_data_api/v0/tests/views/test_course_summaries.py
+12
-1
analytics_data_api/v0/views/course_summaries.py
+6
-1
No files found.
AUTHORS
View file @
e72a5629
...
@@ -8,3 +8,4 @@ Gabe Mulley <gabe@edx.org>
...
@@ -8,3 +8,4 @@ Gabe Mulley <gabe@edx.org>
Jason Bau <jbau@stanford.edu>
Jason Bau <jbau@stanford.edu>
John Jarvis <jarv@edx.org>
John Jarvis <jarv@edx.org>
Dmitry Viskov <dmitry.viskov@webenterprise.ru>
Dmitry Viskov <dmitry.viskov@webenterprise.ru>
Eric Fischer <efischer@edx.org>
analytics_data_api/management/commands/generate_fake_course_data.py
View file @
e72a5629
...
@@ -161,15 +161,17 @@ class Command(BaseCommand):
...
@@ -161,15 +161,17 @@ class Command(BaseCommand):
progress
.
update
(
1
)
progress
.
update
(
1
)
date
=
date
+
datetime
.
timedelta
(
days
=
1
)
date
=
date
+
datetime
.
timedelta
(
days
=
1
)
for
mode
,
ratio
in
enrollment_mode_ratios
.
iteritems
(
):
for
index
,
(
mode
,
ratio
)
in
enumerate
(
enrollment_mode_ratios
.
iteritems
()
):
count
=
int
(
ratio
*
daily_total
)
count
=
int
(
ratio
*
daily_total
)
pass_rate
=
min
(
random
.
normalvariate
(
.
45
+
(
.
1
*
index
),
.
15
),
1.0
)
cumulative_count
=
count
+
random
.
randint
(
0
,
100
)
cumulative_count
=
count
+
random
.
randint
(
0
,
100
)
models
.
CourseMetaSummaryEnrollment
.
objects
.
create
(
models
.
CourseMetaSummaryEnrollment
.
objects
.
create
(
course_id
=
course_id
,
catalog_course_title
=
'Demo Course'
,
catalog_course
=
'Demo_Course'
,
course_id
=
course_id
,
catalog_course_title
=
'Demo Course'
,
catalog_course
=
'Demo_Course'
,
start_time
=
timezone
.
now
()
-
datetime
.
timedelta
(
weeks
=
6
),
start_time
=
timezone
.
now
()
-
datetime
.
timedelta
(
weeks
=
6
),
end_time
=
timezone
.
now
()
+
datetime
.
timedelta
(
weeks
=
10
),
end_time
=
timezone
.
now
()
+
datetime
.
timedelta
(
weeks
=
10
),
pacing_type
=
'self_paced'
,
availability
=
'Starting Soon'
,
enrollment_mode
=
mode
,
count
=
count
,
pacing_type
=
'self_paced'
,
availability
=
'Starting Soon'
,
enrollment_mode
=
mode
,
count
=
count
,
cumulative_count
=
cumulative_count
,
count_change_7_days
=
random
.
randint
(
-
50
,
50
))
cumulative_count
=
cumulative_count
,
count_change_7_days
=
random
.
randint
(
-
50
,
50
),
passing_users
=
int
(
cumulative_count
*
pass_rate
))
models
.
CourseProgramMetadata
.
objects
.
create
(
course_id
=
course_id
,
program_id
=
'Demo_Program'
,
models
.
CourseProgramMetadata
.
objects
.
create
(
course_id
=
course_id
,
program_id
=
'Demo_Program'
,
program_type
=
'Demo'
,
program_title
=
'Demo Program'
)
program_type
=
'Demo'
,
program_title
=
'Demo Program'
)
...
...
analytics_data_api/v0/models.py
View file @
e72a5629
...
@@ -78,6 +78,7 @@ class CourseMetaSummaryEnrollment(BaseCourseModel):
...
@@ -78,6 +78,7 @@ class CourseMetaSummaryEnrollment(BaseCourseModel):
count
=
models
.
IntegerField
(
null
=
False
)
count
=
models
.
IntegerField
(
null
=
False
)
cumulative_count
=
models
.
IntegerField
(
null
=
False
)
cumulative_count
=
models
.
IntegerField
(
null
=
False
)
count_change_7_days
=
models
.
IntegerField
(
default
=
0
)
count_change_7_days
=
models
.
IntegerField
(
default
=
0
)
passing_users
=
models
.
IntegerField
(
default
=
0
)
class
Meta
(
BaseCourseModel
.
Meta
):
class
Meta
(
BaseCourseModel
.
Meta
):
db_table
=
'course_meta_summary_enrollment'
db_table
=
'course_meta_summary_enrollment'
...
...
analytics_data_api/v0/serializers.py
View file @
e72a5629
...
@@ -561,6 +561,7 @@ class CourseMetaSummaryEnrollmentSerializer(ModelSerializerWithCreatedField, Dyn
...
@@ -561,6 +561,7 @@ class CourseMetaSummaryEnrollmentSerializer(ModelSerializerWithCreatedField, Dyn
count
=
serializers
.
IntegerField
(
default
=
0
)
count
=
serializers
.
IntegerField
(
default
=
0
)
cumulative_count
=
serializers
.
IntegerField
(
default
=
0
)
cumulative_count
=
serializers
.
IntegerField
(
default
=
0
)
count_change_7_days
=
serializers
.
IntegerField
(
default
=
0
)
count_change_7_days
=
serializers
.
IntegerField
(
default
=
0
)
passing_users
=
serializers
.
IntegerField
(
default
=
0
)
enrollment_modes
=
serializers
.
SerializerMethodField
()
enrollment_modes
=
serializers
.
SerializerMethodField
()
programs
=
serializers
.
SerializerMethodField
()
programs
=
serializers
.
SerializerMethodField
()
...
...
analytics_data_api/v0/tests/views/test_course_summaries.py
View file @
e72a5629
...
@@ -36,7 +36,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -36,7 +36,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
start_time
=
datetime
.
datetime
(
2016
,
10
,
11
,
tzinfo
=
pytz
.
utc
),
start_time
=
datetime
.
datetime
(
2016
,
10
,
11
,
tzinfo
=
pytz
.
utc
),
end_time
=
datetime
.
datetime
(
2016
,
12
,
18
,
tzinfo
=
pytz
.
utc
),
end_time
=
datetime
.
datetime
(
2016
,
12
,
18
,
tzinfo
=
pytz
.
utc
),
pacing_type
=
'instructor'
,
availability
=
kwargs
[
'availability'
],
enrollment_mode
=
mode
,
pacing_type
=
'instructor'
,
availability
=
kwargs
[
'availability'
],
enrollment_mode
=
mode
,
count
=
5
,
cumulative_count
=
10
,
count_change_7_days
=
1
,
create
=
self
.
now
,)
count
=
5
,
cumulative_count
=
10
,
count_change_7_days
=
1
,
passing_users
=
1
,
create
=
self
.
now
,)
if
'programs'
in
kwargs
and
kwargs
[
'programs'
]:
if
'programs'
in
kwargs
and
kwargs
[
'programs'
]:
# Create a link from this course to a program
# Create a link from this course to a program
G
(
models
.
CourseProgramMetadata
,
course_id
=
model_id
,
program_id
=
CourseSamples
.
program_ids
[
0
],
G
(
models
.
CourseProgramMetadata
,
course_id
=
model_id
,
program_id
=
CourseSamples
.
program_ids
[
0
],
...
@@ -70,6 +70,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -70,6 +70,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
(
'count'
,
count_factor
*
num_modes
),
(
'count'
,
count_factor
*
num_modes
),
(
'cumulative_count'
,
cumulative_count_factor
*
num_modes
),
(
'cumulative_count'
,
cumulative_count_factor
*
num_modes
),
(
'count_change_7_days'
,
count_change_factor
*
num_modes
),
(
'count_change_7_days'
,
count_change_factor
*
num_modes
),
(
'passing_users'
,
count_change_factor
*
num_modes
),
(
'enrollment_modes'
,
{}),
(
'enrollment_modes'
,
{}),
])
])
summary
[
'enrollment_modes'
]
.
update
({
summary
[
'enrollment_modes'
]
.
update
({
...
@@ -77,6 +78,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -77,6 +78,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count'
:
count_factor
,
'count'
:
count_factor
,
'cumulative_count'
:
cumulative_count_factor
,
'cumulative_count'
:
cumulative_count_factor
,
'count_change_7_days'
:
count_change_factor
,
'count_change_7_days'
:
count_change_factor
,
'passing_users'
:
count_change_factor
,
}
for
mode
in
modes
}
for
mode
in
modes
})
})
summary
[
'enrollment_modes'
]
.
update
({
summary
[
'enrollment_modes'
]
.
update
({
...
@@ -84,6 +86,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -84,6 +86,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count'
:
0
,
'count'
:
0
,
'cumulative_count'
:
0
,
'cumulative_count'
:
0
,
'count_change_7_days'
:
0
,
'count_change_7_days'
:
0
,
'passing_users'
:
0
,
}
for
mode
in
set
(
enrollment_modes
.
ALL
)
-
set
(
modes
)
}
for
mode
in
set
(
enrollment_modes
.
ALL
)
-
set
(
modes
)
})
})
no_prof
=
summary
[
'enrollment_modes'
]
.
pop
(
enrollment_modes
.
PROFESSIONAL_NO_ID
)
no_prof
=
summary
[
'enrollment_modes'
]
.
pop
(
enrollment_modes
.
PROFESSIONAL_NO_ID
)
...
@@ -92,6 +95,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -92,6 +95,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count'
:
prof
[
'count'
]
+
no_prof
[
'count'
],
'count'
:
prof
[
'count'
]
+
no_prof
[
'count'
],
'cumulative_count'
:
prof
[
'cumulative_count'
]
+
no_prof
[
'cumulative_count'
],
'cumulative_count'
:
prof
[
'cumulative_count'
]
+
no_prof
[
'cumulative_count'
],
'count_change_7_days'
:
prof
[
'count_change_7_days'
]
+
no_prof
[
'count_change_7_days'
],
'count_change_7_days'
:
prof
[
'count_change_7_days'
]
+
no_prof
[
'count_change_7_days'
],
'passing_users'
:
prof
[
'passing_users'
]
+
no_prof
[
'passing_users'
],
})
})
if
programs
:
if
programs
:
summary
[
'programs'
]
=
[
CourseSamples
.
program_ids
[
0
]]
summary
[
'programs'
]
=
[
CourseSamples
.
program_ids
[
0
]]
...
@@ -159,3 +163,10 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
...
@@ -159,3 +163,10 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
response
=
self
.
authenticated_get
(
self
.
path
(
exclude
=
self
.
always_exclude
[:
1
],
programs
=
[
'True'
]))
response
=
self
.
authenticated_get
(
self
.
path
(
exclude
=
self
.
always_exclude
[:
1
],
programs
=
[
'True'
]))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertItemsEqual
(
response
.
data
,
self
.
all_expected_results
(
programs
=
True
))
self
.
assertItemsEqual
(
response
.
data
,
self
.
all_expected_results
(
programs
=
True
))
@ddt.data
(
'passing_users'
,
)
def
test_exclude
(
self
,
field
):
self
.
generate_data
()
response
=
self
.
authenticated_get
(
self
.
path
(
exclude
=
[
field
]))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
str
(
response
.
data
)
.
count
(
field
),
0
)
analytics_data_api/v0/views/course_summaries.py
View file @
e72a5629
...
@@ -54,7 +54,8 @@ class CourseSummariesView(APIListView):
...
@@ -54,7 +54,8 @@ class CourseSummariesView(APIListView):
model
=
models
.
CourseMetaSummaryEnrollment
model
=
models
.
CourseMetaSummaryEnrollment
model_id_field
=
'course_id'
model_id_field
=
'course_id'
programs_model
=
models
.
CourseProgramMetadata
programs_model
=
models
.
CourseProgramMetadata
count_fields
=
(
'count'
,
'cumulative_count'
,
'count_change_7_days'
)
# are initialized to 0 by default
count_fields
=
(
'count'
,
'cumulative_count'
,
'count_change_7_days'
,
'passing_users'
)
# are initialized to 0 by default
summary_meta_fields
=
[
'catalog_course_title'
,
'catalog_course'
,
'start_time'
,
'end_time'
,
summary_meta_fields
=
[
'catalog_course_title'
,
'catalog_course'
,
'start_time'
,
'end_time'
,
'pacing_type'
,
'availability'
]
# fields to extract from summary model
'pacing_type'
,
'availability'
]
# fields to extract from summary model
...
@@ -120,6 +121,10 @@ class CourseSummariesView(APIListView):
...
@@ -120,6 +121,10 @@ class CourseSummariesView(APIListView):
# don't do expensive looping for programs if we are just going to throw it away
# don't do expensive looping for programs if we are just going to throw it away
field_dict
=
self
.
add_programs
(
field_dict
)
field_dict
=
self
.
add_programs
(
field_dict
)
for
field
in
self
.
exclude
:
for
mode
in
field_dict
[
'enrollment_modes'
]:
_
=
field_dict
[
'enrollment_modes'
][
mode
]
.
pop
(
field
,
None
)
return
field_dict
return
field_dict
def
add_programs
(
self
,
field_dict
):
def
add_programs
(
self
,
field_dict
):
...
...
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