Commit 8448118a by Matt Drayer Committed by Jonathan Piacenti

mattdrayer/api-modulesgroups: API - Added grouping capability for courseware content

initial commit

add tests

back out config change
parent 82668c34
......@@ -357,7 +357,7 @@ class CoursesDetail(APIView):
# get_course_by_id raises an Http404 if the requested course is invalid
# Rather than catching it, we just let it bubble up
try:
course_descriptor = get_course(course_id)
course_descriptor = get_course(course_id, depth=depth_int)
except ValueError:
course_descriptor = None
if course_descriptor:
......@@ -791,6 +791,7 @@ class CourseContentGroupsList(APIView):
"""
response_data = []
group_type = request.QUERY_PARAMS.get('type')
try:
course_descriptor = get_course(course_id)
except ValueError:
......
......@@ -715,6 +715,84 @@ class UsersApiTests(TestCase):
response = self.do_delete(test_uri)
self.assertEqual(response.status_code, 404)
def test_user_course_grades_course_not_found(self):
test_uri = '/api/users'
local_username = self.test_username + str(randint(11, 99))
data = {'email': self.test_email, 'username': local_username, 'password':
self.test_password, 'first_name': self.test_first_name, 'last_name': self.test_last_name}
response = self.do_post(test_uri, data)
user_id = response.data['id']
test_uri = '/api/users/{}/courses/{}/grades'.format(
user_id, 'some/unknown/course')
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_user_course_grades_user_not_found(self):
course = CourseFactory.create()
test_uri = '/api/users/{}/courses/{}/grades'.format(
'9999999', course.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 404)
def test_course_grades(self):
test_uri = '/api/users'
local_username = self.test_username + str(randint(11, 99))
data = {'email': self.test_email, 'username': local_username, 'password':
self.test_password, 'first_name': self.test_first_name, 'last_name': self.test_last_name}
response = self.do_post(test_uri, data)
user_id = response.data['id']
course = CourseFactory.create()
test_data = '<html>{}</html>'.format(str(uuid.uuid4()))
chapter1 = ItemFactory.create(
category="chapter",
parent_location=course.location,
data=test_data,
display_name="Chapter 1"
)
chapter2 = ItemFactory.create(
category="chapter",
parent_location=course.location,
data=test_data,
display_name="Chapter 2"
)
ItemFactory.create(
category="sequential",
parent_location=chapter1.location,
data=test_data,
display_name="Sequence 1",
)
ItemFactory.create(
category="sequential",
parent_location=chapter2.location,
data=test_data,
display_name="Sequence 2",
)
test_uri = '/api/users/{}/courses/{}/grades'.format(
user_id, course.id)
response = self.do_get(test_uri)
self.assertEqual(response.status_code, 200)
print 'data type == ' + response.data.__class__.__name__
print 'data = {}'.format(response.data)
courseware_summary = response.data['courseware_summary']
self.assertEqual(len(courseware_summary), 2)
self.assertEqual(courseware_summary[0]['course'], 'Robot Super Course')
self.assertEqual(courseware_summary[0]['display_name'], 'Chapter 1')
sections = courseware_summary[0]['sections']
self.assertEqual(len(sections), 1)
self.assertEqual(sections[0]['display_name'], 'Sequence 1')
self.assertEqual(sections[0]['graded'], False)
sections = courseware_summary[1]['sections']
self.assertEqual(len(sections), 1)
self.assertEqual(sections[0]['display_name'], 'Sequence 2')
self.assertEqual(sections[0]['graded'], False)
def is_user_profile_created_updated(self, response, data):
"""This function compare response with user profile data """
......
......@@ -10,7 +10,8 @@ urlpatterns = patterns(
url(r'/*$^', users_views.UsersList.as_view()),
url(r'^(?P<user_id>[0-9]+)$', users_views.UsersDetail.as_view()),
url(r'^(?P<user_id>[0-9]+)/courses/*$', users_views.UsersCoursesList.as_view()),
url(r'^(?P<user_id>[0-9]+)/courses/(?P<course_id>[a-zA-Z0-9/_:]+)$', users_views.UsersCoursesDetail.as_view()),
url(r'^(?P<user_id>[0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)$', users_views.UsersCoursesDetail.as_view()),
url(r'^(?P<user_id>[0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/grades$', users_views.UsersCoursesGradesDetail.as_view()),
url(r'^(?P<user_id>[0-9]+)/groups/*$', users_views.UsersGroupsList.as_view()),
url(r'^(?P<user_id>[0-9]+)/groups/(?P<group_id>[0-9]+)$', users_views.UsersGroupsDetail.as_view()),
)
......
......@@ -28,6 +28,9 @@ from util.password_policy_validators import (
)
from util.bad_request_rate_limiter import BadRequestRateLimiter
from courseware import grades
from courseware.courses import get_course
log = logging.getLogger(__name__)
AUDIT_LOG = logging.getLogger("audit")
......@@ -600,3 +603,41 @@ class UsersCoursesDetail(APIView):
if user:
CourseEnrollment.unenroll(user, course_id)
return Response({}, status=status.HTTP_204_NO_CONTENT)
class UsersCoursesGradesDetail(APIView):
permission_classes = (ApiKeyHeaderPermission,)
def get(self, request, user_id, course_id):
"""
GET returns the current gradebook for the user in a course
"""
# @TODO: Add authorization check here once we get caller identity
# Only student can get his/her own information *or* course staff
# can get everyone's grades
try:
# get the full course tree with depth=None which reduces the number of
# round trips to the database
course = get_course(course_id, depth=None)
except ValueError:
return Response({}, status=status.HTTP_404_NOT_FOUND)
# The pre-fetching of groups is done to make auth checks not require an
# additional DB lookup (this kills the Progress page in particular).
try:
student = User.objects.prefetch_related("groups").get(id=user_id)
except ObjectDoesNotExist:
return Response({}, status=status.HTTP_404_NOT_FOUND)
courseware_summary = grades.progress_summary(student, request, course)
grade_summary = grades.grade(student, request, course)
response_data = {
'courseware_summary': courseware_summary,
'grade_summary': grade_summary
}
return Response(response_data)
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