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
654239dc
Commit
654239dc
authored
Mar 11, 2014
by
Greg Price
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2890 from edx/gprice/user-api-with-prefs
Augment user API to allow easier access to user preferences
parents
779d0aab
bbd6f788
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
98 additions
and
5 deletions
+98
-5
common/djangoapps/user_api/models.py
+4
-2
common/djangoapps/user_api/serializers.py
+5
-1
common/djangoapps/user_api/tests/test_views.py
+71
-1
common/djangoapps/user_api/urls.py
+5
-0
common/djangoapps/user_api/views.py
+13
-1
No files found.
common/djangoapps/user_api/models.py
View file @
654239dc
from
django.contrib.auth.models
import
User
from
django.core.validators
import
RegexValidator
from
django.db
import
models
class
UserPreference
(
models
.
Model
):
"""A user's preference, stored as generic text to be processed by client"""
user
=
models
.
ForeignKey
(
User
,
db_index
=
True
,
related_name
=
"+"
)
key
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
KEY_REGEX
=
r"[-_a-zA-Z0-9]+"
user
=
models
.
ForeignKey
(
User
,
db_index
=
True
,
related_name
=
"preferences"
)
key
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
,
validators
=
[
RegexValidator
(
KEY_REGEX
)])
value
=
models
.
TextField
()
class
Meta
:
# pylint: disable=missing-docstring
...
...
common/djangoapps/user_api/serializers.py
View file @
654239dc
...
...
@@ -6,15 +6,19 @@ from user_api.models import UserPreference
class
UserSerializer
(
serializers
.
HyperlinkedModelSerializer
):
name
=
serializers
.
SerializerMethodField
(
"get_name"
)
preferences
=
serializers
.
SerializerMethodField
(
"get_preferences"
)
def
get_name
(
self
,
user
):
profile
=
UserProfile
.
objects
.
get
(
user
=
user
)
return
profile
.
name
def
get_preferences
(
self
,
user
):
return
dict
([(
pref
.
key
,
pref
.
value
)
for
pref
in
user
.
preferences
.
all
()])
class
Meta
:
model
=
User
# This list is the minimal set required by the notification service
fields
=
(
"id"
,
"email"
,
"name"
,
"username"
)
fields
=
(
"id"
,
"email"
,
"name"
,
"username"
,
"preferences"
)
read_only_fields
=
(
"id"
,
"email"
,
"username"
)
...
...
common/djangoapps/user_api/tests/test_views.py
View file @
654239dc
...
...
@@ -66,7 +66,11 @@ class ApiTestCase(TestCase):
def
assertUserIsValid
(
self
,
user
):
"""Assert that the given user result is valid"""
self
.
assertItemsEqual
(
user
.
keys
(),
[
"email"
,
"id"
,
"name"
,
"username"
,
"url"
])
self
.
assertItemsEqual
(
user
.
keys
(),
[
"email"
,
"id"
,
"name"
,
"username"
,
"preferences"
,
"url"
])
self
.
assertItemsEqual
(
user
[
"preferences"
]
.
items
(),
[(
pref
.
key
,
pref
.
value
)
for
pref
in
self
.
prefs
if
pref
.
user
.
id
==
user
[
"id"
]]
)
self
.
assertSelfReferential
(
user
)
def
assertPrefIsValid
(
self
,
pref
):
...
...
@@ -221,6 +225,11 @@ class UserViewSetTest(UserApiTestCase):
"id"
:
user
.
id
,
"name"
:
user
.
profile
.
name
,
"username"
:
user
.
username
,
"preferences"
:
dict
([
(
user_pref
.
key
,
user_pref
.
value
)
for
user_pref
in
self
.
prefs
if
user_pref
.
user
==
user
]),
"url"
:
uri
}
)
...
...
@@ -352,6 +361,11 @@ class UserPreferenceViewSetTest(UserApiTestCase):
"id"
:
pref
.
user
.
id
,
"name"
:
pref
.
user
.
profile
.
name
,
"username"
:
pref
.
user
.
username
,
"preferences"
:
dict
([
(
user_pref
.
key
,
user_pref
.
value
)
for
user_pref
in
self
.
prefs
if
user_pref
.
user
==
pref
.
user
]),
"url"
:
self
.
get_uri_for_user
(
pref
.
user
),
},
"key"
:
pref
.
key
,
...
...
@@ -359,3 +373,59 @@ class UserPreferenceViewSetTest(UserApiTestCase):
"url"
:
uri
,
}
)
class
PreferenceUsersListViewTest
(
UserApiTestCase
):
LIST_URI
=
"/user_api/v1/preferences/key0/users/"
def
test_options
(
self
):
self
.
assertAllowedMethods
(
self
.
LIST_URI
,
[
"OPTIONS"
,
"GET"
,
"HEAD"
])
def
test_put_not_allowed
(
self
):
self
.
assertHttpMethodNotAllowed
(
self
.
request_with_auth
(
"put"
,
self
.
LIST_URI
))
def
test_patch_not_allowed
(
self
):
raise
SkipTest
(
"Django 1.4's test client does not support patch"
)
def
test_delete_not_allowed
(
self
):
self
.
assertHttpMethodNotAllowed
(
self
.
request_with_auth
(
"delete"
,
self
.
LIST_URI
))
def
test_unauthorized
(
self
):
self
.
assertHttpForbidden
(
self
.
client
.
get
(
self
.
LIST_URI
))
@override_settings
(
DEBUG
=
True
)
@override_settings
(
EDX_API_KEY
=
None
)
def
test_debug_auth
(
self
):
self
.
assertHttpOK
(
self
.
client
.
get
(
self
.
LIST_URI
))
def
test_get_basic
(
self
):
result
=
self
.
get_json
(
self
.
LIST_URI
)
self
.
assertEqual
(
result
[
"count"
],
2
)
self
.
assertIsNone
(
result
[
"next"
])
self
.
assertIsNone
(
result
[
"previous"
])
users
=
result
[
"results"
]
self
.
assertEqual
(
len
(
users
),
2
)
for
user
in
users
:
self
.
assertUserIsValid
(
user
)
def
test_get_pagination
(
self
):
first_page
=
self
.
get_json
(
self
.
LIST_URI
,
data
=
{
"page_size"
:
1
})
self
.
assertEqual
(
first_page
[
"count"
],
2
)
first_page_next_uri
=
first_page
[
"next"
]
self
.
assertIsNone
(
first_page
[
"previous"
])
first_page_users
=
first_page
[
"results"
]
self
.
assertEqual
(
len
(
first_page_users
),
1
)
second_page
=
self
.
get_json
(
first_page_next_uri
)
self
.
assertEqual
(
second_page
[
"count"
],
2
)
self
.
assertIsNone
(
second_page
[
"next"
])
second_page_prev_uri
=
second_page
[
"previous"
]
second_page_users
=
second_page
[
"results"
]
self
.
assertEqual
(
len
(
second_page_users
),
1
)
self
.
assertEqual
(
self
.
get_json
(
second_page_prev_uri
),
first_page
)
for
user
in
first_page_users
+
second_page_users
:
self
.
assertUserIsValid
(
user
)
all_user_uris
=
[
user
[
"url"
]
for
user
in
first_page_users
+
second_page_users
]
self
.
assertEqual
(
len
(
set
(
all_user_uris
)),
2
)
common/djangoapps/user_api/urls.py
View file @
654239dc
from
django.conf.urls
import
include
,
patterns
,
url
from
rest_framework
import
routers
from
user_api
import
views
as
user_api_views
from
user_api.models
import
UserPreference
user_api_router
=
routers
.
DefaultRouter
()
...
...
@@ -9,4 +10,8 @@ user_api_router.register(r'user_prefs', user_api_views.UserPreferenceViewSet)
urlpatterns
=
patterns
(
''
,
url
(
r'^v1/'
,
include
(
user_api_router
.
urls
)),
url
(
r'^v1/preferences/(?P<pref_key>{})/users/$'
.
format
(
UserPreference
.
KEY_REGEX
),
user_api_views
.
PreferenceUsersListView
.
as_view
()
),
)
common/djangoapps/user_api/views.py
View file @
654239dc
...
...
@@ -2,6 +2,7 @@ from django.conf import settings
from
django.contrib.auth.models
import
User
from
rest_framework
import
authentication
from
rest_framework
import
filters
from
rest_framework
import
generics
from
rest_framework
import
permissions
from
rest_framework
import
viewsets
from
user_api.serializers
import
UserSerializer
,
UserPreferenceSerializer
...
...
@@ -28,7 +29,7 @@ class ApiKeyHeaderPermission(permissions.BasePermission):
class
UserViewSet
(
viewsets
.
ReadOnlyModelViewSet
):
authentication_classes
=
(
authentication
.
SessionAuthentication
,)
permission_classes
=
(
ApiKeyHeaderPermission
,)
queryset
=
User
.
objects
.
all
()
queryset
=
User
.
objects
.
all
()
.
prefetch_related
(
"preferences"
)
serializer_class
=
UserSerializer
paginate_by
=
10
paginate_by_param
=
"page_size"
...
...
@@ -43,3 +44,14 @@ class UserPreferenceViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class
=
UserPreferenceSerializer
paginate_by
=
10
paginate_by_param
=
"page_size"
class
PreferenceUsersListView
(
generics
.
ListAPIView
):
authentication_classes
=
(
authentication
.
SessionAuthentication
,)
permission_classes
=
(
ApiKeyHeaderPermission
,)
serializer_class
=
UserSerializer
paginate_by
=
10
paginate_by_param
=
"page_size"
def
get_queryset
(
self
):
return
User
.
objects
.
filter
(
preferences__key
=
self
.
kwargs
[
"pref_key"
])
.
prefetch_related
(
"preferences"
)
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