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
bd4e6fc6
Commit
bd4e6fc6
authored
Jul 28, 2014
by
Clinton Blackburn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7 from edx/schema-updates
Schema updates
parents
1018ced0
fbaef361
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
124 additions
and
1970 deletions
+124
-1970
Makefile
+1
-1
analytics_data_api/fixtures/countries.json
+0
-1781
analytics_data_api/fixtures/courses.json
+0
-9
analytics_data_api/fixtures/single_course_activity.json
+4
-4
analytics_data_api/management/commands/generate_fake_enrollment_data.py
+16
-11
analytics_data_api/v0/managers.py
+0
-11
analytics_data_api/v0/models.py
+28
-39
analytics_data_api/v0/serializers.py
+7
-20
analytics_data_api/v0/tests/test_managers.py
+0
-24
analytics_data_api/v0/tests/test_models.py
+18
-9
analytics_data_api/v0/tests/test_views.py
+40
-50
analytics_data_api/v0/views/courses.py
+9
-11
requirements/base.txt
+1
-0
No files found.
Makefile
View file @
bd4e6fc6
...
@@ -50,7 +50,7 @@ syncdb:
...
@@ -50,7 +50,7 @@ syncdb:
$
(
foreach db_name,
$(DATABASES)
,./manage.py syncdb
--migrate
--noinput
--database
=
$(db_name)
;
)
$
(
foreach db_name,
$(DATABASES)
,./manage.py syncdb
--migrate
--noinput
--database
=
$(db_name)
;
)
loaddata
:
syncdb
loaddata
:
syncdb
python manage.py loaddata
courses education_levels countrie
s single_course_activity problem_response_answer_distribution
--database
=
analytics
python manage.py loaddata
education_level
s single_course_activity problem_response_answer_distribution
--database
=
analytics
python manage.py generate_fake_enrollment_data
python manage.py generate_fake_enrollment_data
demo
:
clean requirements loaddata
demo
:
clean requirements loaddata
...
...
analytics_data_api/fixtures/countries.json
deleted
100644 → 0
View file @
1018ced0
[
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"A1"
,
"name"
:
"Anonymous Proxy"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"A2"
,
"name"
:
"Satellite Provider"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"O1"
,
"name"
:
"Other Country"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AD"
,
"name"
:
"Andorra"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AE"
,
"name"
:
"United Arab Emirates"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AF"
,
"name"
:
"Afghanistan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AG"
,
"name"
:
"Antigua and Barbuda"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AI"
,
"name"
:
"Anguilla"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AL"
,
"name"
:
"Albania"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AM"
,
"name"
:
"Armenia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AO"
,
"name"
:
"Angola"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AP"
,
"name"
:
"Asia/Pacific Region"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AQ"
,
"name"
:
"Antarctica"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AR"
,
"name"
:
"Argentina"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AS"
,
"name"
:
"American Samoa"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AT"
,
"name"
:
"Austria"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AU"
,
"name"
:
"Australia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AW"
,
"name"
:
"Aruba"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AX"
,
"name"
:
"Aland Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"AZ"
,
"name"
:
"Azerbaijan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BA"
,
"name"
:
"Bosnia and Herzegovina"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BB"
,
"name"
:
"Barbados"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BD"
,
"name"
:
"Bangladesh"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BE"
,
"name"
:
"Belgium"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BF"
,
"name"
:
"Burkina Faso"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BG"
,
"name"
:
"Bulgaria"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BH"
,
"name"
:
"Bahrain"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BI"
,
"name"
:
"Burundi"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BJ"
,
"name"
:
"Benin"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BL"
,
"name"
:
"Saint Bartelemey"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BM"
,
"name"
:
"Bermuda"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BN"
,
"name"
:
"Brunei Darussalam"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BO"
,
"name"
:
"Bolivia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BQ"
,
"name"
:
"Bonaire, Saint Eustatius and Saba"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BR"
,
"name"
:
"Brazil"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BS"
,
"name"
:
"Bahamas"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BT"
,
"name"
:
"Bhutan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BV"
,
"name"
:
"Bouvet Island"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BW"
,
"name"
:
"Botswana"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BY"
,
"name"
:
"Belarus"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"BZ"
,
"name"
:
"Belize"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CA"
,
"name"
:
"Canada"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CC"
,
"name"
:
"Cocos (Keeling) Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CD"
,
"name"
:
"Congo, The Democratic Republic of the"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CF"
,
"name"
:
"Central African Republic"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CG"
,
"name"
:
"Congo"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CH"
,
"name"
:
"Switzerland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CI"
,
"name"
:
"Cote d'Ivoire"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CK"
,
"name"
:
"Cook Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CL"
,
"name"
:
"Chile"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CM"
,
"name"
:
"Cameroon"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CN"
,
"name"
:
"China"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CO"
,
"name"
:
"Colombia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CR"
,
"name"
:
"Costa Rica"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CU"
,
"name"
:
"Cuba"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CV"
,
"name"
:
"Cape Verde"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CW"
,
"name"
:
"Curacao"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CX"
,
"name"
:
"Christmas Island"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CY"
,
"name"
:
"Cyprus"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"CZ"
,
"name"
:
"Czech Republic"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DE"
,
"name"
:
"Germany"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DJ"
,
"name"
:
"Djibouti"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DK"
,
"name"
:
"Denmark"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DM"
,
"name"
:
"Dominica"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DO"
,
"name"
:
"Dominican Republic"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"DZ"
,
"name"
:
"Algeria"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"EC"
,
"name"
:
"Ecuador"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"EE"
,
"name"
:
"Estonia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"EG"
,
"name"
:
"Egypt"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"EH"
,
"name"
:
"Western Sahara"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ER"
,
"name"
:
"Eritrea"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ES"
,
"name"
:
"Spain"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ET"
,
"name"
:
"Ethiopia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"EU"
,
"name"
:
"Europe"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FI"
,
"name"
:
"Finland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FJ"
,
"name"
:
"Fiji"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FK"
,
"name"
:
"Falkland Islands (Malvinas)"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FM"
,
"name"
:
"Micronesia, Federated States of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FO"
,
"name"
:
"Faroe Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"FR"
,
"name"
:
"France"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GA"
,
"name"
:
"Gabon"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GB"
,
"name"
:
"United Kingdom"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GD"
,
"name"
:
"Grenada"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GE"
,
"name"
:
"Georgia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GF"
,
"name"
:
"French Guiana"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GG"
,
"name"
:
"Guernsey"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GH"
,
"name"
:
"Ghana"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GI"
,
"name"
:
"Gibraltar"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GL"
,
"name"
:
"Greenland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GM"
,
"name"
:
"Gambia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GN"
,
"name"
:
"Guinea"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GP"
,
"name"
:
"Guadeloupe"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GQ"
,
"name"
:
"Equatorial Guinea"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GR"
,
"name"
:
"Greece"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GS"
,
"name"
:
"South Georgia and the South Sandwich Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GT"
,
"name"
:
"Guatemala"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GU"
,
"name"
:
"Guam"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GW"
,
"name"
:
"Guinea-Bissau"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"GY"
,
"name"
:
"Guyana"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HK"
,
"name"
:
"Hong Kong"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HM"
,
"name"
:
"Heard Island and McDonald Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HN"
,
"name"
:
"Honduras"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HR"
,
"name"
:
"Croatia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HT"
,
"name"
:
"Haiti"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"HU"
,
"name"
:
"Hungary"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ID"
,
"name"
:
"Indonesia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IE"
,
"name"
:
"Ireland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IL"
,
"name"
:
"Israel"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IM"
,
"name"
:
"Isle of Man"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IN"
,
"name"
:
"India"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IO"
,
"name"
:
"British Indian Ocean Territory"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IQ"
,
"name"
:
"Iraq"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IR"
,
"name"
:
"Iran, Islamic Republic of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IS"
,
"name"
:
"Iceland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"IT"
,
"name"
:
"Italy"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"JE"
,
"name"
:
"Jersey"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"JM"
,
"name"
:
"Jamaica"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"JO"
,
"name"
:
"Jordan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"JP"
,
"name"
:
"Japan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KE"
,
"name"
:
"Kenya"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KG"
,
"name"
:
"Kyrgyzstan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KH"
,
"name"
:
"Cambodia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KI"
,
"name"
:
"Kiribati"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KM"
,
"name"
:
"Comoros"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KN"
,
"name"
:
"Saint Kitts and Nevis"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KP"
,
"name"
:
"Korea, Democratic People's Republic of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KR"
,
"name"
:
"Korea, Republic of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KW"
,
"name"
:
"Kuwait"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KY"
,
"name"
:
"Cayman Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"KZ"
,
"name"
:
"Kazakhstan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LA"
,
"name"
:
"Lao People's Democratic Republic"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LB"
,
"name"
:
"Lebanon"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LC"
,
"name"
:
"Saint Lucia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LI"
,
"name"
:
"Liechtenstein"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LK"
,
"name"
:
"Sri Lanka"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LR"
,
"name"
:
"Liberia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LS"
,
"name"
:
"Lesotho"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LT"
,
"name"
:
"Lithuania"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LU"
,
"name"
:
"Luxembourg"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LV"
,
"name"
:
"Latvia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"LY"
,
"name"
:
"Libyan Arab Jamahiriya"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MA"
,
"name"
:
"Morocco"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MC"
,
"name"
:
"Monaco"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MD"
,
"name"
:
"Moldova, Republic of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ME"
,
"name"
:
"Montenegro"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MF"
,
"name"
:
"Saint Martin"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MG"
,
"name"
:
"Madagascar"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MH"
,
"name"
:
"Marshall Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MK"
,
"name"
:
"Macedonia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ML"
,
"name"
:
"Mali"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MM"
,
"name"
:
"Myanmar"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MN"
,
"name"
:
"Mongolia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MO"
,
"name"
:
"Macao"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MP"
,
"name"
:
"Northern Mariana Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MQ"
,
"name"
:
"Martinique"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MR"
,
"name"
:
"Mauritania"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MS"
,
"name"
:
"Montserrat"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MT"
,
"name"
:
"Malta"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MU"
,
"name"
:
"Mauritius"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MV"
,
"name"
:
"Maldives"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MW"
,
"name"
:
"Malawi"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MX"
,
"name"
:
"Mexico"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MY"
,
"name"
:
"Malaysia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"MZ"
,
"name"
:
"Mozambique"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NA"
,
"name"
:
"Namibia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NC"
,
"name"
:
"New Caledonia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NE"
,
"name"
:
"Niger"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NF"
,
"name"
:
"Norfolk Island"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NG"
,
"name"
:
"Nigeria"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NI"
,
"name"
:
"Nicaragua"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NL"
,
"name"
:
"Netherlands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NO"
,
"name"
:
"Norway"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NP"
,
"name"
:
"Nepal"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NR"
,
"name"
:
"Nauru"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NU"
,
"name"
:
"Niue"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"NZ"
,
"name"
:
"New Zealand"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"OM"
,
"name"
:
"Oman"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PA"
,
"name"
:
"Panama"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PE"
,
"name"
:
"Peru"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PF"
,
"name"
:
"French Polynesia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PG"
,
"name"
:
"Papua New Guinea"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PH"
,
"name"
:
"Philippines"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PK"
,
"name"
:
"Pakistan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PL"
,
"name"
:
"Poland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PM"
,
"name"
:
"Saint Pierre and Miquelon"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PN"
,
"name"
:
"Pitcairn"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PR"
,
"name"
:
"Puerto Rico"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PS"
,
"name"
:
"Palestinian Territory"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PT"
,
"name"
:
"Portugal"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PW"
,
"name"
:
"Palau"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"PY"
,
"name"
:
"Paraguay"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"QA"
,
"name"
:
"Qatar"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"RE"
,
"name"
:
"Reunion"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"RO"
,
"name"
:
"Romania"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"RS"
,
"name"
:
"Serbia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"RU"
,
"name"
:
"Russian Federation"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"RW"
,
"name"
:
"Rwanda"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SA"
,
"name"
:
"Saudi Arabia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SB"
,
"name"
:
"Solomon Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SC"
,
"name"
:
"Seychelles"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SD"
,
"name"
:
"Sudan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SE"
,
"name"
:
"Sweden"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SG"
,
"name"
:
"Singapore"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SH"
,
"name"
:
"Saint Helena"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SI"
,
"name"
:
"Slovenia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SJ"
,
"name"
:
"Svalbard and Jan Mayen"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SK"
,
"name"
:
"Slovakia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SL"
,
"name"
:
"Sierra Leone"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SM"
,
"name"
:
"San Marino"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SN"
,
"name"
:
"Senegal"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SO"
,
"name"
:
"Somalia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SR"
,
"name"
:
"Suriname"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SS"
,
"name"
:
"South Sudan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ST"
,
"name"
:
"Sao Tome and Principe"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SV"
,
"name"
:
"El Salvador"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SX"
,
"name"
:
"Sint Maarten"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SY"
,
"name"
:
"Syrian Arab Republic"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"SZ"
,
"name"
:
"Swaziland"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TC"
,
"name"
:
"Turks and Caicos Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TD"
,
"name"
:
"Chad"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TF"
,
"name"
:
"French Southern Territories"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TG"
,
"name"
:
"Togo"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TH"
,
"name"
:
"Thailand"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TJ"
,
"name"
:
"Tajikistan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TK"
,
"name"
:
"Tokelau"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TL"
,
"name"
:
"Timor-Leste"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TM"
,
"name"
:
"Turkmenistan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TN"
,
"name"
:
"Tunisia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TO"
,
"name"
:
"Tonga"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TR"
,
"name"
:
"Turkey"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TT"
,
"name"
:
"Trinidad and Tobago"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TV"
,
"name"
:
"Tuvalu"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TW"
,
"name"
:
"Taiwan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"TZ"
,
"name"
:
"Tanzania, United Republic of"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"UA"
,
"name"
:
"Ukraine"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"UG"
,
"name"
:
"Uganda"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"UM"
,
"name"
:
"United States Minor Outlying Islands"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"US"
,
"name"
:
"United States"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"UY"
,
"name"
:
"Uruguay"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"UZ"
,
"name"
:
"Uzbekistan"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VA"
,
"name"
:
"Holy See (Vatican City State)"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VC"
,
"name"
:
"Saint Vincent and the Grenadines"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VE"
,
"name"
:
"Venezuela"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VG"
,
"name"
:
"Virgin Islands, British"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VI"
,
"name"
:
"Virgin Islands, U.S."
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VN"
,
"name"
:
"Vietnam"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"VU"
,
"name"
:
"Vanuatu"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"WF"
,
"name"
:
"Wallis and Futuna"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"WS"
,
"name"
:
"Samoa"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"YE"
,
"name"
:
"Yemen"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"YT"
,
"name"
:
"Mayotte"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ZA"
,
"name"
:
"South Africa"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ZM"
,
"name"
:
"Zambia"
}
},
{
"model"
:
"v0.country"
,
"fields"
:
{
"code"
:
"ZW"
,
"name"
:
"Zimbabwe"
}
}
]
\ No newline at end of file
analytics_data_api/fixtures/courses.json
deleted
100644 → 0
View file @
1018ced0
[
{
"pk"
:
1
,
"model"
:
"v0.course"
,
"fields"
:
{
"course_id"
:
"edX/DemoX/Demo_Course"
}
}
]
analytics_data_api/fixtures/single_course_activity.json
View file @
bd4e6fc6
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
"pk"
:
40
,
"pk"
:
40
,
"model"
:
"v0.CourseActivityByWeek"
,
"model"
:
"v0.CourseActivityByWeek"
,
"fields"
:
{
"fields"
:
{
"course
"
:
[
"edX/DemoX/Demo_Course"
]
,
"course
_id"
:
"edX/DemoX/Demo_Course"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"activity_type"
:
"posted_forum"
,
"activity_type"
:
"posted_forum"
,
"count"
:
100
,
"count"
:
100
,
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
"pk"
:
106
,
"pk"
:
106
,
"model"
:
"v0.CourseActivityByWeek"
,
"model"
:
"v0.CourseActivityByWeek"
,
"fields"
:
{
"fields"
:
{
"course
"
:
[
"edX/DemoX/Demo_Course"
]
,
"course
_id"
:
"edX/DemoX/Demo_Course"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"activity_type"
:
"attempted_problem"
,
"activity_type"
:
"attempted_problem"
,
"count"
:
200
,
"count"
:
200
,
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
"pk"
:
201
,
"pk"
:
201
,
"model"
:
"v0.CourseActivityByWeek"
,
"model"
:
"v0.CourseActivityByWeek"
,
"fields"
:
{
"fields"
:
{
"course
"
:
[
"edX/DemoX/Demo_Course"
]
,
"course
_id"
:
"edX/DemoX/Demo_Course"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"activity_type"
:
"any"
,
"activity_type"
:
"any"
,
"count"
:
300
,
"count"
:
300
,
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
"pk"
:
725
,
"pk"
:
725
,
"model"
:
"v0.CourseActivityByWeek"
,
"model"
:
"v0.CourseActivityByWeek"
,
"fields"
:
{
"fields"
:
{
"course
"
:
[
"edX/DemoX/Demo_Course"
]
,
"course
_id"
:
"edX/DemoX/Demo_Course"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"interval_start"
:
"2014-05-24T00:00:00Z"
,
"activity_type"
:
"played_video"
,
"activity_type"
:
"played_video"
,
"count"
:
400
,
"count"
:
400
,
...
...
analytics_data_api/management/commands/generate_fake_enrollment_data.py
View file @
bd4e6fc6
# pylint: disable=line-too-long
import
datetime
import
datetime
import
random
import
random
...
@@ -23,7 +25,7 @@ class Command(BaseCommand):
...
@@ -23,7 +25,7 @@ class Command(BaseCommand):
def
handle
(
self
,
*
args
,
**
options
):
def
handle
(
self
,
*
args
,
**
options
):
days
=
120
days
=
120
course
=
models
.
Course
.
objects
.
first
()
course
_id
=
'edX/DemoX/Demo_Course'
start_date
=
datetime
.
date
(
year
=
2014
,
month
=
1
,
day
=
1
)
start_date
=
datetime
.
date
(
year
=
2014
,
month
=
1
,
day
=
1
)
genders
=
{
genders
=
{
...
@@ -58,33 +60,36 @@ class Command(BaseCommand):
...
@@ -58,33 +60,36 @@ class Command(BaseCommand):
birth_years
=
dict
(
zip
(
birth_years
,
ratios
))
birth_years
=
dict
(
zip
(
birth_years
,
ratios
))
# Delete existing data
# Delete existing data
for
model
in
[
models
.
CourseEnrollmentDaily
,
models
.
CourseEnrollmentByGender
,
models
.
CourseEnrollmentByEducation
,
for
model
in
[
models
.
CourseEnrollmentDaily
,
models
.
CourseEnrollmentByBirthYear
,
models
.
CourseEnrollmentByCountry
]:
models
.
CourseEnrollmentByGender
,
models
.
CourseEnrollmentByEducation
,
models
.
CourseEnrollmentByBirthYear
,
models
.
CourseEnrollmentByCountry
]:
model
.
objects
.
all
()
.
delete
()
model
.
objects
.
all
()
.
delete
()
# Create new data
data
# Create new data
daily_total
=
1500
daily_total
=
1500
for
i
in
range
(
days
):
for
i
in
range
(
days
):
daily_total
=
get_count
(
daily_total
)
daily_total
=
get_count
(
daily_total
)
date
=
start_date
+
datetime
.
timedelta
(
days
=
i
)
date
=
start_date
+
datetime
.
timedelta
(
days
=
i
)
models
.
CourseEnrollmentDaily
.
objects
.
create
(
course
=
course
,
date
=
date
,
count
=
daily_total
)
models
.
CourseEnrollmentDaily
.
objects
.
create
(
course
_id
=
course_id
,
date
=
date
,
count
=
daily_total
)
for
gender
,
ratio
in
genders
.
iteritems
():
for
gender
,
ratio
in
genders
.
iteritems
():
count
=
int
(
ratio
*
daily_total
)
count
=
int
(
ratio
*
daily_total
)
models
.
CourseEnrollmentByGender
.
objects
.
create
(
course
=
course
,
date
=
date
,
count
=
count
,
gender
=
gender
)
models
.
CourseEnrollmentByGender
.
objects
.
create
(
course
_id
=
course_id
,
date
=
date
,
count
=
count
,
gender
=
gender
)
for
short_name
,
ratio
in
education_levels
.
iteritems
():
for
short_name
,
ratio
in
education_levels
.
iteritems
():
education_level
=
models
.
EducationLevel
.
objects
.
get
(
short_name
=
short_name
)
education_level
=
models
.
EducationLevel
.
objects
.
get
(
short_name
=
short_name
)
count
=
int
(
ratio
*
daily_total
)
count
=
int
(
ratio
*
daily_total
)
models
.
CourseEnrollmentByEducation
.
objects
.
create
(
course
=
course
,
date
=
date
,
count
=
count
,
models
.
CourseEnrollmentByEducation
.
objects
.
create
(
course
_id
=
course_id
,
date
=
date
,
count
=
count
,
education_level
=
education_level
)
education_level
=
education_level
)
for
code
,
ratio
in
countries
.
iteritems
():
for
country_code
,
ratio
in
countries
.
iteritems
():
country
=
models
.
Country
.
objects
.
get
(
code
=
code
)
count
=
int
(
ratio
*
daily_total
)
count
=
int
(
ratio
*
daily_total
)
models
.
CourseEnrollmentByCountry
.
objects
.
create
(
course
=
course
,
date
=
date
,
count
=
count
,
country
=
country
)
models
.
CourseEnrollmentByCountry
.
objects
.
create
(
course_id
=
course_id
,
date
=
date
,
count
=
count
,
country_code
=
country_code
)
for
birth_year
,
ratio
in
birth_years
.
iteritems
():
for
birth_year
,
ratio
in
birth_years
.
iteritems
():
count
=
int
(
ratio
*
daily_total
)
count
=
int
(
ratio
*
daily_total
)
models
.
CourseEnrollmentByBirthYear
.
objects
.
create
(
course
=
course
,
date
=
date
,
count
=
count
,
models
.
CourseEnrollmentByBirthYear
.
objects
.
create
(
course
_id
=
course_id
,
date
=
date
,
count
=
count
,
birth_year
=
birth_year
)
birth_year
=
birth_year
)
analytics_data_api/v0/managers.py
deleted
100644 → 0
View file @
1018ced0
from
django.db
import
models
class
CourseManager
(
models
.
Manager
):
def
get_by_natural_key
(
self
,
course_id
):
return
self
.
get
(
course_id
=
course_id
)
class
CountryManager
(
models
.
Manager
):
def
get_by_natural_key
(
self
,
code
):
return
self
.
get
(
code
=
code
)
analytics_data_api/v0/models.py
View file @
bd4e6fc6
from
collections
import
namedtuple
from
django.db
import
models
from
django.db
import
models
from
analytics_data_api.v0.managers
import
CourseManager
,
CountryManager
from
iso3166
import
countries
class
Course
(
models
.
Model
):
course_id
=
models
.
CharField
(
unique
=
True
,
max_length
=
255
)
objects
=
CourseManager
()
# pylint: disable=no-value-for-parameter
class
Meta
(
object
):
db_table
=
'courses'
class
CourseActivityByWeek
(
models
.
Model
):
class
CourseActivityByWeek
(
models
.
Model
):
...
@@ -17,7 +9,7 @@ class CourseActivityByWeek(models.Model):
...
@@ -17,7 +9,7 @@ class CourseActivityByWeek(models.Model):
class
Meta
(
object
):
class
Meta
(
object
):
db_table
=
'course_activity'
db_table
=
'course_activity'
course
=
models
.
ForeignKey
(
Course
,
null
=
False
)
course
_id
=
models
.
CharField
(
max_length
=
255
)
interval_start
=
models
.
DateTimeField
()
interval_start
=
models
.
DateTimeField
()
interval_end
=
models
.
DateTimeField
()
interval_end
=
models
.
DateTimeField
()
activity_type
=
models
.
CharField
(
db_index
=
True
,
max_length
=
255
)
activity_type
=
models
.
CharField
(
db_index
=
True
,
max_length
=
255
)
...
@@ -26,33 +18,35 @@ class CourseActivityByWeek(models.Model):
...
@@ -26,33 +18,35 @@ class CourseActivityByWeek(models.Model):
@classmethod
@classmethod
def
get_most_recent
(
cls
,
course_id
,
activity_type
):
def
get_most_recent
(
cls
,
course_id
,
activity_type
):
"""Activity for the week that was mostly recently computed."""
"""Activity for the week that was mostly recently computed."""
return
cls
.
objects
.
filter
(
course_
_course_
id
=
course_id
,
activity_type
=
activity_type
)
.
latest
(
'interval_end'
)
return
cls
.
objects
.
filter
(
course_id
=
course_id
,
activity_type
=
activity_type
)
.
latest
(
'interval_end'
)
class
BaseCourseEnrollment
(
models
.
Model
):
class
BaseCourseEnrollment
(
models
.
Model
):
course
=
models
.
ForeignKey
(
Course
,
null
=
False
)
course
_id
=
models
.
CharField
(
max_length
=
255
)
date
=
models
.
DateField
(
null
=
False
,
db_index
=
True
)
date
=
models
.
DateField
(
null
=
False
,
db_index
=
True
)
count
=
models
.
IntegerField
(
null
=
False
)
count
=
models
.
IntegerField
(
null
=
False
)
created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
class
Meta
(
object
):
class
Meta
(
object
):
abstract
=
True
abstract
=
True
get_latest_by
=
'date'
get_latest_by
=
'date'
index_together
=
[(
'course_id'
,
'date'
,)]
class
CourseEnrollmentDaily
(
BaseCourseEnrollment
):
class
CourseEnrollmentDaily
(
BaseCourseEnrollment
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
db_table
=
'course_enrollment_daily'
db_table
=
'course_enrollment_daily'
ordering
=
(
'date'
,
'course'
)
ordering
=
(
'date'
,
'course
_id
'
)
unique_together
=
[(
'course'
,
'date'
,)]
unique_together
=
[(
'course
_id
'
,
'date'
,)]
class
CourseEnrollmentByBirthYear
(
BaseCourseEnrollment
):
class
CourseEnrollmentByBirthYear
(
BaseCourseEnrollment
):
birth_year
=
models
.
IntegerField
(
null
=
False
)
birth_year
=
models
.
IntegerField
(
null
=
False
)
class
Meta
(
BaseCourseEnrollment
.
Meta
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
db_table
=
'course_enrollment_birth_year'
db_table
=
'course_enrollment_birth_year
_daily
'
ordering
=
(
'date'
,
'course'
,
'birth_year'
)
ordering
=
(
'date'
,
'course
_id
'
,
'birth_year'
)
unique_together
=
[(
'course'
,
'date'
,
'birth_year'
)]
unique_together
=
[(
'course
_id
'
,
'date'
,
'birth_year'
)]
class
EducationLevel
(
models
.
Model
):
class
EducationLevel
(
models
.
Model
):
...
@@ -70,18 +64,18 @@ class CourseEnrollmentByEducation(BaseCourseEnrollment):
...
@@ -70,18 +64,18 @@ class CourseEnrollmentByEducation(BaseCourseEnrollment):
education_level
=
models
.
ForeignKey
(
EducationLevel
)
education_level
=
models
.
ForeignKey
(
EducationLevel
)
class
Meta
(
BaseCourseEnrollment
.
Meta
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
db_table
=
'course_enrollment_education_level'
db_table
=
'course_enrollment_education_level
_daily
'
ordering
=
(
'date'
,
'course'
,
'education_level'
)
ordering
=
(
'date'
,
'course
_id
'
,
'education_level'
)
unique_together
=
[(
'course'
,
'date'
,
'education_level'
)]
unique_together
=
[(
'course
_id
'
,
'date'
,
'education_level'
)]
class
CourseEnrollmentByGender
(
BaseCourseEnrollment
):
class
CourseEnrollmentByGender
(
BaseCourseEnrollment
):
gender
=
models
.
CharField
(
max_length
=
255
,
null
=
False
)
gender
=
models
.
CharField
(
max_length
=
255
,
null
=
False
)
class
Meta
(
BaseCourseEnrollment
.
Meta
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
db_table
=
'course_enrollment_gender'
db_table
=
'course_enrollment_gender
_daily
'
ordering
=
(
'date'
,
'course'
,
'gender'
)
ordering
=
(
'date'
,
'course
_id
'
,
'gender'
)
unique_together
=
[(
'course'
,
'date'
,
'gender'
)]
unique_together
=
[(
'course
_id
'
,
'date'
,
'gender'
)]
class
ProblemResponseAnswerDistribution
(
models
.
Model
):
class
ProblemResponseAnswerDistribution
(
models
.
Model
):
...
@@ -102,23 +96,18 @@ class ProblemResponseAnswerDistribution(models.Model):
...
@@ -102,23 +96,18 @@ class ProblemResponseAnswerDistribution(models.Model):
created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
db_column
=
'created'
)
created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
db_column
=
'created'
)
class
Country
(
models
.
Model
):
Country
=
namedtuple
(
'Country'
,
'name, code'
)
code
=
models
.
CharField
(
max_length
=
2
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
,
null
=
False
)
objects
=
CountryManager
()
# pylint: disable=no-value-for-parameter
class
Meta
(
object
):
db_table
=
'countries'
def
__unicode__
(
self
):
return
"{0} - {1}"
.
format
(
self
.
code
,
self
.
name
)
class
CourseEnrollmentByCountry
(
BaseCourseEnrollment
):
class
CourseEnrollmentByCountry
(
BaseCourseEnrollment
):
country
=
models
.
ForeignKey
(
Country
,
null
=
False
,
db_column
=
'country_code'
)
country_code
=
models
.
CharField
(
max_length
=
255
,
null
=
False
,
db_column
=
'country_code'
)
@property
def
country
(
self
):
country
=
countries
.
get
(
self
.
country_code
)
return
Country
(
country
.
name
,
country
.
alpha2
)
class
Meta
(
BaseCourseEnrollment
.
Meta
):
class
Meta
(
BaseCourseEnrollment
.
Meta
):
db_table
=
'course_enrollment_location'
db_table
=
'course_enrollment_location
_current
'
ordering
=
(
'date'
,
'course
'
,
'country
'
)
ordering
=
(
'date'
,
'course
_id'
,
'country_code
'
)
unique_together
=
[(
'course
'
,
'date'
,
'country
'
)]
unique_together
=
[(
'course
_id'
,
'date'
,
'country_code
'
)]
analytics_data_api/v0/serializers.py
View file @
bd4e6fc6
...
@@ -3,16 +3,7 @@ from rest_framework import serializers
...
@@ -3,16 +3,7 @@ from rest_framework import serializers
from
analytics_data_api.v0
import
models
from
analytics_data_api.v0
import
models
class
CourseIdMixin
(
object
):
class
CourseActivityByWeekSerializer
(
serializers
.
ModelSerializer
):
def
get_course_id
(
self
,
obj
):
return
obj
.
course
.
course_id
class
RequiredSerializerMethodField
(
serializers
.
SerializerMethodField
):
required
=
True
class
CourseActivityByWeekSerializer
(
serializers
.
ModelSerializer
,
CourseIdMixin
):
"""
"""
Representation of CourseActivityByWeek that excludes the id field.
Representation of CourseActivityByWeek that excludes the id field.
...
@@ -20,8 +11,6 @@ class CourseActivityByWeekSerializer(serializers.ModelSerializer, CourseIdMixin)
...
@@ -20,8 +11,6 @@ class CourseActivityByWeekSerializer(serializers.ModelSerializer, CourseIdMixin)
particular record is likely to change unexpectedly so we avoid exposing it.
particular record is likely to change unexpectedly so we avoid exposing it.
"""
"""
course_id
=
RequiredSerializerMethodField
(
'get_course_id'
)
class
Meta
(
object
):
class
Meta
(
object
):
model
=
models
.
CourseActivityByWeek
model
=
models
.
CourseActivityByWeek
fields
=
(
'interval_start'
,
'interval_end'
,
'activity_type'
,
'count'
,
'course_id'
)
fields
=
(
'interval_start'
,
'interval_end'
,
'activity_type'
,
'count'
,
'course_id'
)
...
@@ -51,8 +40,7 @@ class ProblemResponseAnswerDistributionSerializer(serializers.ModelSerializer):
...
@@ -51,8 +40,7 @@ class ProblemResponseAnswerDistributionSerializer(serializers.ModelSerializer):
)
)
class
BaseCourseEnrollmentModelSerializer
(
serializers
.
ModelSerializer
,
CourseIdMixin
):
class
BaseCourseEnrollmentModelSerializer
(
serializers
.
ModelSerializer
):
course_id
=
RequiredSerializerMethodField
(
'get_course_id'
)
date
=
serializers
.
DateField
(
format
=
settings
.
DATE_FORMAT
)
date
=
serializers
.
DateField
(
format
=
settings
.
DATE_FORMAT
)
...
@@ -64,11 +52,9 @@ class CourseEnrollmentDailySerializer(BaseCourseEnrollmentModelSerializer):
...
@@ -64,11 +52,9 @@ class CourseEnrollmentDailySerializer(BaseCourseEnrollmentModelSerializer):
fields
=
(
'course_id'
,
'date'
,
'count'
)
fields
=
(
'course_id'
,
'date'
,
'count'
)
# pylint: disable=no-value-for-parameter
class
CountrySerializer
(
serializers
.
Serializer
):
class
CountrySerializer
(
serializers
.
ModelSerializer
):
code
=
serializers
.
CharField
()
class
Meta
(
object
):
name
=
serializers
.
CharField
()
model
=
models
.
Country
fields
=
(
'code'
,
'name'
)
# pylint: disable=no-value-for-parameter
# pylint: disable=no-value-for-parameter
...
@@ -79,7 +65,8 @@ class EducationLevelSerializer(serializers.ModelSerializer):
...
@@ -79,7 +65,8 @@ class EducationLevelSerializer(serializers.ModelSerializer):
class
CourseEnrollmentByCountrySerializer
(
BaseCourseEnrollmentModelSerializer
):
class
CourseEnrollmentByCountrySerializer
(
BaseCourseEnrollmentModelSerializer
):
country
=
CountrySerializer
()
# pylint: disable=unexpected-keyword-arg
country
=
CountrySerializer
(
many
=
False
)
class
Meta
(
object
):
class
Meta
(
object
):
model
=
models
.
CourseEnrollmentByCountry
model
=
models
.
CourseEnrollmentByCountry
...
...
analytics_data_api/v0/tests/test_managers.py
deleted
100644 → 0
View file @
1018ced0
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.test
import
TestCase
from
django_dynamic_fixture
import
G
from
analytics_data_api.v0.models
import
Course
,
Country
class
CourseManagerTests
(
TestCase
):
def
test_get_by_natural_key
(
self
):
course_id
=
'edX/DemoX/Demo_Course'
self
.
assertRaises
(
ObjectDoesNotExist
,
Course
.
objects
.
get_by_natural_key
,
course_id
)
course
=
G
(
Course
,
course_id
=
course_id
)
self
.
assertEqual
(
course
,
Course
.
objects
.
get_by_natural_key
(
course_id
))
class
CountryManagerTests
(
TestCase
):
def
test_get_by_natural_key
(
self
):
code
=
'US'
self
.
assertRaises
(
ObjectDoesNotExist
,
Country
.
objects
.
get_by_natural_key
,
code
)
country
=
G
(
Country
,
code
=
code
)
self
.
assertEqual
(
country
,
Country
.
objects
.
get_by_natural_key
(
code
))
analytics_data_api/v0/tests/test_models.py
View file @
bd4e6fc6
...
@@ -2,22 +2,31 @@ from django.test import TestCase
...
@@ -2,22 +2,31 @@ from django.test import TestCase
from
django_dynamic_fixture
import
G
from
django_dynamic_fixture
import
G
from
analytics_data_api.v0
.models
import
EducationLevel
,
Country
from
analytics_data_api.v0
import
models
class
EducationLevelTests
(
TestCase
):
class
EducationLevelTests
(
TestCase
):
def
test_unicode
(
self
):
def
test_unicode
(
self
):
short_name
=
'high_school'
short_name
=
'high_school'
name
=
'High School'
name
=
'High School'
education_level
=
G
(
EducationLevel
,
short_name
=
short_name
,
name
=
name
)
education_level
=
G
(
models
.
EducationLevel
,
short_name
=
short_name
,
name
=
name
)
self
.
assertEqual
(
unicode
(
education_level
),
"{0} - {1}"
.
format
(
short_name
,
name
))
self
.
assertEqual
(
unicode
(
education_level
),
"{0} - {1}"
.
format
(
short_name
,
name
))
class
CountryTests
(
TestCase
):
class
CountryTests
(
TestCase
):
def
test_unicode
(
self
):
# pylint: disable=no-member
code
=
'US'
def
test_attributes
(
self
):
name
=
'United States of America'
country
=
models
.
Country
(
'Canada'
,
'CA'
)
country
=
G
(
Country
,
code
=
code
,
name
=
name
)
self
.
assertEqual
(
country
.
code
,
'CA'
)
self
.
assertEqual
(
country
.
name
,
'Canada'
)
self
.
assertEqual
(
unicode
(
country
),
"{0} - {1}"
.
format
(
code
,
name
))
class
CourseEnrollmentByCountryTests
(
TestCase
):
def
test_country
(
self
):
country
=
models
.
Country
(
'United States'
,
'US'
)
instance
=
G
(
models
.
CourseEnrollmentByCountry
,
country_code
=
country
.
code
)
self
.
assertEqual
(
instance
.
country
,
country
)
analytics_data_api/v0/tests/test_views.py
View file @
bd4e6fc6
...
@@ -4,10 +4,10 @@
...
@@ -4,10 +4,10 @@
import
StringIO
import
StringIO
import
csv
import
csv
import
datetime
import
datetime
import
random
from
django.conf
import
settings
from
django.conf
import
settings
from
django_dynamic_fixture
import
G
from
django_dynamic_fixture
import
G
from
iso3166
import
countries
import
pytz
import
pytz
from
analytics_data_api.v0
import
models
from
analytics_data_api.v0
import
models
...
@@ -17,19 +17,19 @@ from analyticsdataserver.tests import TestCaseWithAuthentication
...
@@ -17,19 +17,19 @@ from analyticsdataserver.tests import TestCaseWithAuthentication
class
CourseActivityLastWeekTest
(
TestCaseWithAuthentication
):
class
CourseActivityLastWeekTest
(
TestCaseWithAuthentication
):
# pylint: disable=line-too-long
def
setUp
(
self
):
def
setUp
(
self
):
super
(
CourseActivityLastWeekTest
,
self
)
.
setUp
()
super
(
CourseActivityLastWeekTest
,
self
)
.
setUp
()
self
.
course_id
=
'edX/DemoX/Demo_Course'
self
.
course_id
=
'edX/DemoX/Demo_Course'
self
.
course
=
G
(
models
.
Course
,
course_id
=
self
.
course_id
)
interval_start
=
'2014-05-24T00:00:00Z'
interval_start
=
'2014-05-24T00:00:00Z'
interval_end
=
'2014-06-01T00:00:00Z'
interval_end
=
'2014-06-01T00:00:00Z'
G
(
models
.
CourseActivityByWeek
,
course
=
self
.
course
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
G
(
models
.
CourseActivityByWeek
,
course
_id
=
self
.
course_id
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
activity_type
=
'posted_forum'
,
count
=
100
)
activity_type
=
'posted_forum'
,
count
=
100
)
G
(
models
.
CourseActivityByWeek
,
course
=
self
.
course
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
G
(
models
.
CourseActivityByWeek
,
course
_id
=
self
.
course_id
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
activity_type
=
'attempted_problem'
,
count
=
200
)
activity_type
=
'attempted_problem'
,
count
=
200
)
G
(
models
.
CourseActivityByWeek
,
course
=
self
.
course
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
G
(
models
.
CourseActivityByWeek
,
course
_id
=
self
.
course_id
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
activity_type
=
'any'
,
count
=
300
)
activity_type
=
'any'
,
count
=
300
)
G
(
models
.
CourseActivityByWeek
,
course
=
self
.
course
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
G
(
models
.
CourseActivityByWeek
,
course
_id
=
self
.
course_id
,
interval_start
=
interval_start
,
interval_end
=
interval_end
,
activity_type
=
'played_video'
,
count
=
400
)
activity_type
=
'played_video'
,
count
=
400
)
def
test_activity
(
self
):
def
test_activity
(
self
):
...
@@ -86,27 +86,18 @@ class CourseEnrollmentViewTestCase(object):
...
@@ -86,27 +86,18 @@ class CourseEnrollmentViewTestCase(object):
path
=
None
path
=
None
order_by
=
[]
order_by
=
[]
def
_get_non_existent_course_id
(
self
):
course_id
=
random
.
randint
(
100
,
9999
)
if
not
models
.
Course
.
objects
.
filter
(
course_id
=
course_id
)
.
exists
():
return
course_id
return
self
.
_get_non_existent_course_id
()
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
raise
NotImplementedError
raise
NotImplementedError
def
test_get_not_found
(
self
):
def
test_get_not_found
(
self
):
""" Requests made against non-existent courses should return a 404 """
""" Requests made against non-existent courses should return a 404 """
course_id
=
self
.
_get_non_existent_course_id
()
course_id
=
'edX/DemoX/Non_Existent_Course'
self
.
assertFalse
(
self
.
model
.
objects
.
filter
(
course__course_id
=
course_id
)
.
exists
())
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
course_id
,
self
.
path
))
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
course_id
,
self
.
path
))
self
.
assertEquals
(
response
.
status_code
,
404
)
self
.
assertEquals
(
response
.
status_code
,
404
)
def
test_get
(
self
):
def
test_get
(
self
):
# Validate the basic response status
# Validate the basic response status
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course
.
course
_id
,
self
.
path
,))
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course_id
,
self
.
path
,))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
# Validate the data is correct and sorted chronologically
# Validate the data is correct and sorted chronologically
...
@@ -114,7 +105,7 @@ class CourseEnrollmentViewTestCase(object):
...
@@ -114,7 +105,7 @@ class CourseEnrollmentViewTestCase(object):
self
.
assertEquals
(
response
.
data
,
expected
)
self
.
assertEquals
(
response
.
data
,
expected
)
def
test_get_csv
(
self
):
def
test_get_csv
(
self
):
path
=
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course
.
course
_id
,
self
.
path
,)
path
=
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course_id
,
self
.
path
,)
csv_content_type
=
'text/csv'
csv_content_type
=
'text/csv'
response
=
self
.
authenticated_get
(
path
,
HTTP_ACCEPT
=
csv_content_type
)
response
=
self
.
authenticated_get
(
path
,
HTTP_ACCEPT
=
csv_content_type
)
...
@@ -142,17 +133,15 @@ class CourseEnrollmentViewTestCase(object):
...
@@ -142,17 +133,15 @@ class CourseEnrollmentViewTestCase(object):
self
.
assertIntervalFilteringWorks
(
expected
,
self
.
date
,
self
.
date
+
datetime
.
timedelta
(
days
=
1
))
self
.
assertIntervalFilteringWorks
(
expected
,
self
.
date
,
self
.
date
+
datetime
.
timedelta
(
days
=
1
))
def
assertIntervalFilteringWorks
(
self
,
expected_response
,
start_date
,
end_date
):
def
assertIntervalFilteringWorks
(
self
,
expected_response
,
start_date
,
end_date
):
course
=
self
.
course
# If start date is after date of existing data, no data should be returned
# If start date is after date of existing data, no data should be returned
date
=
(
start_date
+
datetime
.
timedelta
(
days
=
30
))
.
strftime
(
settings
.
DATE_FORMAT
)
date
=
(
start_date
+
datetime
.
timedelta
(
days
=
30
))
.
strftime
(
settings
.
DATE_FORMAT
)
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s?start_date=
%
s'
%
(
course
.
course_id
,
self
.
path
,
date
))
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s?start_date=
%
s'
%
(
self
.
course_id
,
self
.
path
,
date
))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertListEqual
([],
response
.
data
)
self
.
assertListEqual
([],
response
.
data
)
# If end date is before date of existing data, no data should be returned
# If end date is before date of existing data, no data should be returned
date
=
(
start_date
-
datetime
.
timedelta
(
days
=
30
))
.
strftime
(
settings
.
DATE_FORMAT
)
date
=
(
start_date
-
datetime
.
timedelta
(
days
=
30
))
.
strftime
(
settings
.
DATE_FORMAT
)
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s?end_date=
%
s'
%
(
course
.
course_id
,
self
.
path
,
date
))
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s?end_date=
%
s'
%
(
self
.
course_id
,
self
.
path
,
date
))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertListEqual
([],
response
.
data
)
self
.
assertListEqual
([],
response
.
data
)
...
@@ -160,7 +149,7 @@ class CourseEnrollmentViewTestCase(object):
...
@@ -160,7 +149,7 @@ class CourseEnrollmentViewTestCase(object):
start_date
=
start_date
.
strftime
(
settings
.
DATE_FORMAT
)
start_date
=
start_date
.
strftime
(
settings
.
DATE_FORMAT
)
end_date
=
end_date
.
strftime
(
settings
.
DATE_FORMAT
)
end_date
=
end_date
.
strftime
(
settings
.
DATE_FORMAT
)
response
=
self
.
authenticated_get
(
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s?start_date=
%
s&end_date=
%
s'
%
(
course
.
course_id
,
self
.
path
,
start_date
,
end_date
))
'/api/v0/courses/
%
s
%
s?start_date=
%
s&end_date=
%
s'
%
(
self
.
course_id
,
self
.
path
,
start_date
,
end_date
))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertListEqual
(
response
.
data
,
expected_response
)
self
.
assertListEqual
(
response
.
data
,
expected_response
)
...
@@ -172,20 +161,20 @@ class CourseEnrollmentByBirthYearViewTests(TestCaseWithAuthentication, CourseEnr
...
@@ -172,20 +161,20 @@ class CourseEnrollmentByBirthYearViewTests(TestCaseWithAuthentication, CourseEnr
@classmethod
@classmethod
def
setUpClass
(
cls
):
def
setUpClass
(
cls
):
cls
.
course
=
G
(
models
.
Course
)
cls
.
course
_id
=
'edX/DemoX/Demo_Course'
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
,
birth_year
=
1956
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
,
birth_year
=
1956
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
,
birth_year
=
1986
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
,
birth_year
=
1986
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
10
),
birth_year
=
1956
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
10
),
birth_year
=
1956
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
10
),
birth_year
=
1986
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
10
),
birth_year
=
1986
)
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
return
[
return
[
{
'course_id'
:
str
(
ce
.
course
.
course
_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
{
'course_id'
:
str
(
ce
.
course_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
'birth_year'
:
ce
.
birth_year
}
for
ce
in
args
]
'birth_year'
:
ce
.
birth_year
}
for
ce
in
args
]
def
test_get
(
self
):
def
test_get
(
self
):
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course
.
course
_id
,
self
.
path
,))
response
=
self
.
authenticated_get
(
'/api/v0/courses/
%
s
%
s'
%
(
self
.
course_id
,
self
.
path
,))
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
expected
=
self
.
get_expected_response
(
*
self
.
model
.
objects
.
filter
(
date
=
self
.
date
))
expected
=
self
.
get_expected_response
(
*
self
.
model
.
objects
.
filter
(
date
=
self
.
date
))
...
@@ -205,16 +194,16 @@ class CourseEnrollmentByEducationViewTests(TestCaseWithAuthentication, CourseEnr
...
@@ -205,16 +194,16 @@ class CourseEnrollmentByEducationViewTests(TestCaseWithAuthentication, CourseEnr
def
setUpClass
(
cls
):
def
setUpClass
(
cls
):
cls
.
el1
=
G
(
models
.
EducationLevel
,
name
=
'Doctorate'
,
short_name
=
'doctorate'
)
cls
.
el1
=
G
(
models
.
EducationLevel
,
name
=
'Doctorate'
,
short_name
=
'doctorate'
)
cls
.
el2
=
G
(
models
.
EducationLevel
,
name
=
'Top Secret'
,
short_name
=
'top_secret'
)
cls
.
el2
=
G
(
models
.
EducationLevel
,
name
=
'Top Secret'
,
short_name
=
'top_secret'
)
cls
.
course
=
G
(
models
.
Course
)
cls
.
course
_id
=
'edX/DemoX/Demo_Course'
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
,
education_level
=
cls
.
el1
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
,
education_level
=
cls
.
el1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
,
education_level
=
cls
.
el2
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
,
education_level
=
cls
.
el2
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
2
),
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
2
),
education_level
=
cls
.
el2
)
education_level
=
cls
.
el2
)
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
return
[
return
[
{
'course_id'
:
str
(
ce
.
course
.
course
_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
{
'course_id'
:
str
(
ce
.
course_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
'education_level'
:
{
'name'
:
ce
.
education_level
.
name
,
'short_name'
:
ce
.
education_level
.
short_name
}}
for
'education_level'
:
{
'name'
:
ce
.
education_level
.
name
,
'short_name'
:
ce
.
education_level
.
short_name
}}
for
ce
in
args
]
ce
in
args
]
...
@@ -226,15 +215,15 @@ class CourseEnrollmentByGenderViewTests(TestCaseWithAuthentication, CourseEnroll
...
@@ -226,15 +215,15 @@ class CourseEnrollmentByGenderViewTests(TestCaseWithAuthentication, CourseEnroll
@classmethod
@classmethod
def
setUpClass
(
cls
):
def
setUpClass
(
cls
):
cls
.
course
=
G
(
models
.
Course
)
cls
.
course
_id
=
'edX/DemoX/Demo_Course'
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
gender
=
'm'
,
date
=
cls
.
date
,
count
=
34
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
gender
=
'm'
,
date
=
cls
.
date
,
count
=
34
)
G
(
cls
.
model
,
course
=
cls
.
course
,
gender
=
'f'
,
date
=
cls
.
date
,
count
=
45
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
gender
=
'f'
,
date
=
cls
.
date
,
count
=
45
)
G
(
cls
.
model
,
course
=
cls
.
course
,
gender
=
'f'
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
2
),
count
=
45
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
gender
=
'f'
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
2
),
count
=
45
)
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
return
[
return
[
{
'course_id'
:
str
(
ce
.
course
.
course
_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
{
'course_id'
:
str
(
ce
.
course_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
'gender'
:
ce
.
gender
}
for
ce
in
args
]
'gender'
:
ce
.
gender
}
for
ce
in
args
]
...
@@ -275,14 +264,14 @@ class CourseEnrollmentViewTests(TestCaseWithAuthentication, CourseEnrollmentView
...
@@ -275,14 +264,14 @@ class CourseEnrollmentViewTests(TestCaseWithAuthentication, CourseEnrollmentView
@classmethod
@classmethod
def
setUpClass
(
cls
):
def
setUpClass
(
cls
):
cls
.
course
=
G
(
models
.
Course
)
cls
.
course
_id
=
'edX/DemoX/Demo_Course'
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
,
count
=
203
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
,
count
=
203
)
G
(
cls
.
model
,
course
=
cls
.
course
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
5
),
count
=
203
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
5
),
count
=
203
)
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
return
[
return
[
{
'course_id'
:
str
(
ce
.
course
.
course
_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
)}
{
'course_id'
:
str
(
ce
.
course_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
)}
for
ce
in
args
]
for
ce
in
args
]
...
@@ -291,15 +280,16 @@ class CourseEnrollmentByLocationViewTests(TestCaseWithAuthentication, CourseEnro
...
@@ -291,15 +280,16 @@ class CourseEnrollmentByLocationViewTests(TestCaseWithAuthentication, CourseEnro
model
=
models
.
CourseEnrollmentByCountry
model
=
models
.
CourseEnrollmentByCountry
def
get_expected_response
(
self
,
*
args
):
def
get_expected_response
(
self
,
*
args
):
args
=
sorted
(
args
,
key
=
lambda
item
:
(
item
.
date
,
item
.
course_id
,
item
.
country
.
code
))
return
[
return
[
{
'course_id'
:
str
(
ce
.
course
.
course
_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
{
'course_id'
:
str
(
ce
.
course_id
),
'count'
:
ce
.
count
,
'date'
:
ce
.
date
.
strftime
(
settings
.
DATE_FORMAT
),
'country'
:
{
'code'
:
ce
.
country
.
code
,
'name'
:
ce
.
country
.
name
}}
for
ce
in
args
]
'country'
:
{
'code'
:
ce
.
country
.
code
,
'name'
:
ce
.
country
.
name
}}
for
ce
in
args
]
@classmethod
@classmethod
def
setUpClass
(
cls
):
def
setUpClass
(
cls
):
cls
.
course
=
G
(
models
.
Course
)
cls
.
course
_id
=
'edX/DemoX/Demo_Course'
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
cls
.
date
=
datetime
.
date
(
2014
,
1
,
1
)
G
(
cls
.
model
,
course
=
cls
.
course
,
country
=
G
(
models
.
Country
),
count
=
455
,
date
=
cls
.
date
)
cls
.
country
=
countries
.
get
(
'US'
)
G
(
cls
.
model
,
course
=
cls
.
course
,
country
=
G
(
models
.
Country
),
count
=
356
,
date
=
cls
.
date
)
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
country_code
=
'US'
,
count
=
455
,
date
=
cls
.
date
)
G
(
cls
.
model
,
course
=
cls
.
course
,
country
=
G
(
models
.
Country
),
count
=
12
,
G
(
cls
.
model
,
course
_id
=
cls
.
course_id
,
country_code
=
'CA'
,
count
=
356
,
date
=
cls
.
date
)
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
29
))
G
(
cls
.
model
,
course_id
=
cls
.
course_id
,
country_code
=
'IN'
,
count
=
12
,
date
=
cls
.
date
-
datetime
.
timedelta
(
days
=
29
))
analytics_data_api/v0/views/courses.py
View file @
bd4e6fc6
...
@@ -5,7 +5,6 @@ from django.core.exceptions import ObjectDoesNotExist
...
@@ -5,7 +5,6 @@ from django.core.exceptions import ObjectDoesNotExist
from
django.db.models
import
Max
from
django.db.models
import
Max
from
django.http
import
Http404
from
django.http
import
Http404
from
rest_framework
import
generics
from
rest_framework
import
generics
from
rest_framework.generics
import
get_object_or_404
from
analytics_data_api.v0
import
models
,
serializers
from
analytics_data_api.v0
import
models
,
serializers
...
@@ -53,8 +52,11 @@ class CourseActivityMostRecentWeekView(generics.RetrieveAPIView):
...
@@ -53,8 +52,11 @@ class CourseActivityMostRecentWeekView(generics.RetrieveAPIView):
class
BaseCourseEnrollmentView
(
generics
.
ListAPIView
):
class
BaseCourseEnrollmentView
(
generics
.
ListAPIView
):
def
get_course_or_404
(
self
):
def
verify_course_exists_or_404
(
self
,
course_id
):
return
get_object_or_404
(
models
.
Course
,
course_id
=
self
.
kwargs
.
get
(
'course_id'
))
if
self
.
model
.
objects
.
filter
(
course_id
=
course_id
)
.
exists
():
return
True
raise
Http404
def
apply_date_filtering
(
self
,
queryset
):
def
apply_date_filtering
(
self
,
queryset
):
if
'start_date'
in
self
.
request
.
QUERY_PARAMS
or
'end_date'
in
self
.
request
.
QUERY_PARAMS
:
if
'start_date'
in
self
.
request
.
QUERY_PARAMS
or
'end_date'
in
self
.
request
.
QUERY_PARAMS
:
...
@@ -77,8 +79,9 @@ class BaseCourseEnrollmentView(generics.ListAPIView):
...
@@ -77,8 +79,9 @@ class BaseCourseEnrollmentView(generics.ListAPIView):
return
queryset
return
queryset
def
get_queryset
(
self
):
def
get_queryset
(
self
):
course
=
self
.
get_course_or_404
()
course_id
=
self
.
kwargs
.
get
(
'course_id'
)
queryset
=
self
.
model
.
objects
.
filter
(
course
=
course
)
self
.
verify_course_exists_or_404
(
course_id
)
queryset
=
self
.
model
.
objects
.
filter
(
course_id
=
course_id
)
queryset
=
self
.
apply_date_filtering
(
queryset
)
queryset
=
self
.
apply_date_filtering
(
queryset
)
return
queryset
return
queryset
...
@@ -185,9 +188,4 @@ class CourseEnrollmentByLocationView(BaseCourseEnrollmentView):
...
@@ -185,9 +188,4 @@ class CourseEnrollmentByLocationView(BaseCourseEnrollmentView):
"""
"""
serializer_class
=
serializers
.
CourseEnrollmentByCountrySerializer
serializer_class
=
serializers
.
CourseEnrollmentByCountrySerializer
model
=
models
.
CourseEnrollmentByCountry
def
get_queryset
(
self
):
course
=
self
.
get_course_or_404
()
queryset
=
models
.
CourseEnrollmentByCountry
.
objects
.
filter
(
course
=
course
)
queryset
=
self
.
apply_date_filtering
(
queryset
)
return
queryset
requirements/base.txt
View file @
bd4e6fc6
...
@@ -6,3 +6,4 @@ djangorestframework==2.3.5
...
@@ -6,3 +6,4 @@ djangorestframework==2.3.5
ipython==2.1.0
ipython==2.1.0
django-rest-swagger==0.1.14
django-rest-swagger==0.1.14
djangorestframework-csv==1.3.3
djangorestframework-csv==1.3.3
iso3166==0.1
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