Commit c907daa4 by Zia Fazal Committed by Jonathan Piacenti

New API to get users

Added new API to get enrolled and not enrolled users in Course Content
Group: MCKIN-1027

Also contains:

* Changes base on Matt's Feedback
* Further changes based on Matt's feedback
parent 508dfa68
...@@ -38,6 +38,7 @@ class CoursesApiTests(TestCase): ...@@ -38,6 +38,7 @@ class CoursesApiTests(TestCase):
self.test_server_prefix = 'https://testserver' self.test_server_prefix = 'https://testserver'
self.base_courses_uri = '/api/courses' self.base_courses_uri = '/api/courses'
self.base_groups_uri = '/api/groups' self.base_groups_uri = '/api/groups'
self.base_users_uri = '/api/users'
self.test_group_name = 'Alpha Group' self.test_group_name = 'Alpha Group'
self.course = CourseFactory.create() self.course = CourseFactory.create()
...@@ -1028,3 +1029,75 @@ class CoursesApiTests(TestCase): ...@@ -1028,3 +1029,75 @@ class CoursesApiTests(TestCase):
) )
response = self.do_get(test_uri) response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
def test_course_content_users_list_get(self):
test_uri = '{}/{}/groups'.format(self.base_course_content_uri, self.course_project.id)
test_uri_users = '{}/{}/users'.format(self.base_course_content_uri, self.course_project.id)
test_course_users_uri = self.base_courses_uri + '/' + self.test_course_id + '/users'
# Create a group and add it to course module
data = {'name': 'Alpha Group', 'type': 'test'}
response = self.do_post(self.base_groups_uri, data)
self.assertEqual(response.status_code, 201)
group_id = response.data['id']
data = {'group_id': group_id}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
# Create another group and add it to course module
data = {'name': 'Beta Group', 'type': 'project'}
response = self.do_post(self.base_groups_uri, data)
self.assertEqual(response.status_code, 201)
another_group_id = response.data['id']
data = {'group_id': another_group_id}
response = self.do_post(test_uri, data)
self.assertEqual(response.status_code, 201)
# create a 5 new users
for i in xrange(1, 6):
data = {
'email': 'test{}@example.com'.format(i),
'username': 'test_user{}'.format(i),
'password': 'test_pass',
'first_name': 'John{}'.format(i),
'last_name': 'Doe{}'.format(i)
}
response = self.do_post(self.base_users_uri, data)
self.assertEqual(response.status_code, 201)
created_user_id = response.data['id']
#add two users to Alpha Group and one to Beta Group and keep two without any group
if i <= 3:
add_to_group = group_id
if i > 2:
add_to_group = another_group_id
test_group_users_uri = '{}/{}/users'.format(self.base_groups_uri, add_to_group)
data = {'user_id': created_user_id}
response = self.do_post(test_group_users_uri, data)
self.assertEqual(response.status_code, 201)
#enroll one user in Alpha Group and one in Beta Group created user
if i >= 2:
response = self.do_post(test_course_users_uri, data)
self.assertEqual(response.status_code, 201)
response = self.do_get('{}?enrolled={}'.format(test_uri_users, 'True'))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 2)
response = self.do_get('{}?enrolled={}'.format(test_uri_users, 'False'))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
#filter by group id
response = self.do_get('{}?enrolled={}&group_id={}'.format(test_uri_users, 'true', group_id))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
response = self.do_get('{}?enrolled={}&group_id={}'.format(test_uri_users, 'false', group_id))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
#filter by group type
response = self.do_get('{}?enrolled={}&type={}'.format(test_uri_users, 'true', 'project'))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
...@@ -15,6 +15,7 @@ urlpatterns = patterns( ...@@ -15,6 +15,7 @@ urlpatterns = patterns(
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/groups/(?P<group_id>[0-9]+)$', courses_views.CourseContentGroupsDetail.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/groups/(?P<group_id>[0-9]+)$', courses_views.CourseContentGroupsDetail.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/groups/*$', courses_views.CourseContentGroupsList.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/groups/*$', courses_views.CourseContentGroupsList.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/children/*$', courses_views.CourseContentList.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/children/*$', courses_views.CourseContentList.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)/users/*$', courses_views.CourseContentUsersList.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)$', courses_views.CourseContentDetail.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/(?P<content_id>[a-zA-Z0-9/_:]+)$', courses_views.CourseContentDetail.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/*$', courses_views.CourseContentList.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/content/*$', courses_views.CourseContentList.as_view()),
url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/groups/(?P<group_id>[0-9]+)$', courses_views.CoursesGroupsDetail.as_view()), url(r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/groups/(?P<group_id>[0-9]+)$', courses_views.CoursesGroupsDetail.as_view()),
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from collections import OrderedDict from collections import OrderedDict
import logging import logging
import itertools
from lxml import etree from lxml import etree
from StringIO import StringIO from StringIO import StringIO
...@@ -9,12 +10,13 @@ from django.contrib.auth.models import Group, User ...@@ -9,12 +10,13 @@ from django.contrib.auth.models import Group, User
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404 from django.http import Http404
from rest_framework import status from rest_framework import status, generics
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from api_manager.permissions import ApiKeyHeaderPermission from api_manager.permissions import ApiKeyHeaderPermission
from api_manager.models import CourseGroupRelationship, CourseContentGroupRelationship, GroupProfile from api_manager.models import CourseGroupRelationship, CourseContentGroupRelationship, GroupProfile
from api_manager.users.serializers import UserSerializer
from courseware import module_render from courseware import module_render
from courseware.courses import get_course, get_course_about_section, get_course_info_section from courseware.courses import get_course, get_course_about_section, get_course_info_section
from courseware.model_data import FieldDataCache from courseware.model_data import FieldDataCache
...@@ -844,3 +846,47 @@ class CourseContentGroupsDetail(APIView): ...@@ -844,3 +846,47 @@ class CourseContentGroupsDetail(APIView):
'group_id': group_id, 'group_id': group_id,
} }
return Response(response_data, status=status.HTTP_200_OK) return Response(response_data, status=status.HTTP_200_OK)
class CourseContentUsersList(generics.ListAPIView):
"""
### The CourseContentUsersList view allows clients to users enrolled and
users not enrolled for course within all groups of course
- URI: ```/api/courses/{course_id}/content/{content_id}/users?enrolled={enrolment_status}&group_id={group_id}&type={group_type}```
- GET: Returns a JSON representation of users enrolled or not enrolled
### Use Cases/Notes:
* Use CourseContentUsersList to grab the users enrolled in Course content group
* Use CourseContentUsersList to grab the users not enrolled in Course content group
"""
permission_classes = (ApiKeyHeaderPermission,)
serializer_class = UserSerializer
def get_queryset(self):
"""
GET retrieves the list of users who registered for a given course content
and list of users who are not registered for that group course content.
'enrolled' query parameter for filtering user' enrolment status
'group_id' query parameter is available for filtering by group.
'type' query parameter is available for filtering by group_type.
"""
course_id = self.kwargs['course_id']
content_id = self.kwargs['content_id']
enrolled = self.request.QUERY_PARAMS.get('enrolled', 'True')
group_type = self.request.QUERY_PARAMS.get('type', None)
group_id = self.request.QUERY_PARAMS.get('group_id', None)
groups = CourseContentGroupRelationship.objects.filter(course_id=course_id, content_id=content_id)
if group_id:
groups = groups.filter(group__group__id=group_id)
if group_type:
groups = groups.filter(group__group_type=group_type)
lookup_group_ids = groups.values_list('group_id', flat=True)
users = User.objects.filter(groups__id__in=lookup_group_ids)
enrolled_users = CourseEnrollment.users_enrolled_in(course_id).filter(groups__id__in=lookup_group_ids)
if enrolled in ['True', 'true']:
queryset = enrolled_users
else:
queryset = list(itertools.ifilterfalse(lambda x: x in enrolled_users, users))
return queryset
...@@ -10,5 +10,5 @@ class UserSerializer(serializers.ModelSerializer): ...@@ -10,5 +10,5 @@ class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
""" Serializer/field specification """ """ Serializer/field specification """
model = User model = User
fields = ("id", "email", "username") fields = ("id", "email", "username", "first_name", "last_name")
read_only_fields = ("id", "email", "username") read_only_fields = ("id", "email", "username")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment