From 3de3238b9a80e03c8a686e276571ca33af8e6ce0 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 21 Apr 2014 15:09:12 -0400 Subject: [PATCH 1/2] wip --- lms/djangoapps/api_manager/groups_views.py | 26 ++++++++- lms/djangoapps/api_manager/models.py | 16 ++++++ .../api_manager/tests/test_groups_views.py | 53 ++++++++----------- 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/lms/djangoapps/api_manager/groups_views.py b/lms/djangoapps/api_manager/groups_views.py index 4bf3d2a0028b..2bf7ec2a6490 100644 --- a/lms/djangoapps/api_manager/groups_views.py +++ b/lms/djangoapps/api_manager/groups_views.py @@ -1,5 +1,6 @@ """ API implementation for group-oriented interactions. """ import uuid +import json from django.contrib.auth.models import Group, User from django.core.exceptions import ObjectDoesNotExist @@ -10,7 +11,7 @@ from rest_framework.response import Response from api_manager.permissions import ApiKeyHeaderPermission -from api_manager.models import GroupRelationship, CourseGroupRelationship +from api_manager.models import GroupRelationship, CourseGroupRelationship, GroupProfile from xmodule.modulestore.django import modulestore from xmodule.modulestore import Location, InvalidLocationError @@ -43,13 +44,23 @@ def group_list(request): # Group name must be unique, but we need to support dupes group = Group.objects.create(name=str(uuid.uuid4())) original_group_name = request.DATA['name'] + group.name = '{:04d}: {}'.format(group.id, original_group_name) group.record_active = True group.record_date_created = timezone.now() group.record_date_modified = timezone.now() group.save() + # Relationship model also allows us to use duplicate names GroupRelationship.objects.create(name=original_group_name, group_id=group.id, parent_group=None) + + # allow for optional meta information about groups, this will end up in the GroupProfile table + group_type = request.DATA.get('group_type') + data = request.DATA.get('data') + + if group_type or data: + profile, _ = GroupProfile.objects.get_or_create(group_id=group.id, group_type=group_type, data=data) + response_data = {'id': group.id, 'name': original_group_name} base_uri = _generate_base_uri(request) response_data['uri'] = '{}/{}'.format(base_uri, group.id) @@ -80,6 +91,19 @@ def group_detail(request, group_id): response_data['resources'].append({'uri': resource_uri}) resource_uri = '{}/groups'.format(base_uri) response_data['resources'].append({'uri': resource_uri}) + + # see if there is an (optional) GroupProfile + try: + existing_group_profile = GroupProfile.objects.get(group_id=group_id) + if existing_group_profile.group_type: + response_data['group_type'] = existing_group_profile.group_type + data = existing_group_profile.data + if data: + print '******* data = {0}'.format(data) + response_data['data'] = json.loads(data) + except ObjectDoesNotExist: + pass + response_status = status.HTTP_200_OK else: response_status = status.HTTP_404_NOT_FOUND diff --git a/lms/djangoapps/api_manager/models.py b/lms/djangoapps/api_manager/models.py index fec4eb37dd14..62bb23f7ad62 100644 --- a/lms/djangoapps/api_manager/models.py +++ b/lms/djangoapps/api_manager/models.py @@ -92,3 +92,19 @@ class CourseGroupRelationship(models.Model): """ course_id = models.CharField(max_length=255, db_index=True) group = models.ForeignKey(Group, db_index=True) + + +class GroupProfile(models.Model): + """ + This table will provide additional tables regarding groups. This has a foreign key to + the auth_groups table + """ + + class Meta: + db_table = "auth_groupprofile" + + group = models.ForeignKey(Group, db_index=True) + group_type = models.CharField(null=True, max_length=32, db_index=True) + + data = models.TextField(blank=True) # JSON dictionary for generic key/value pairs + diff --git a/lms/djangoapps/api_manager/tests/test_groups_views.py b/lms/djangoapps/api_manager/tests/test_groups_views.py index 33ac7521c3e3..67d007813cab 100644 --- a/lms/djangoapps/api_manager/tests/test_groups_views.py +++ b/lms/djangoapps/api_manager/tests/test_groups_views.py @@ -7,6 +7,7 @@ from random import randint import unittest import uuid +import json from django.conf import settings from django.core.cache import cache @@ -75,7 +76,6 @@ def do_delete(self, uri): response = self.client.delete(uri, headers=headers) return response - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_list_post(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -96,7 +96,6 @@ def test_group_list_post(self): # response = self.do_post(self.base_groups_uri, data) # self.assertEqual(response.status_code, 409) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_detail_get(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -110,13 +109,31 @@ def test_group_detail_get(self): self.assertEqual(response.data['uri'], confirm_uri) self.assertEqual(response.data['name'], self.test_group_name) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') + def test_group_list_get_with_profile(self): + data = { + 'name': self.test_group_name, + 'group_type': 'series', + 'data': json.dumps({'display_name': 'My first series'}) + } + response = self.do_post(self.base_groups_uri, data) + self.assertGreater(response.data['id'], 0) + group_id = response.data['id'] + + test_uri = self.base_groups_uri + '/' + str(group_id) + response = self.do_get(test_uri) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data['id'], group_id) + confirm_uri = self.test_server_prefix + test_uri + self.assertEqual(response.data['uri'], confirm_uri) + self.assertEqual(response.data['name'], self.test_group_name) + self.assertEqual(response.data['group_type'], 'series') + self.assertEqual(response.data['data']['display_name'],'My first series') + def test_group_detail_get_undefined(self): test_uri = self.base_groups_uri + '/123456789' response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_list_post(self): local_username = self.test_username + str(randint(11, 99)) data = {'email': self.test_email, 'username': local_username, 'password': self.test_password} @@ -136,7 +153,6 @@ def test_group_users_list_post(self): self.assertEqual(response.data['group_id'], str(group_id)) self.assertEqual(response.data['user_id'], str(user_id)) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_list_post_duplicate(self): local_username = self.test_username + str(randint(11, 99)) data = {'email': self.test_email, 'username': local_username, 'password': self.test_password} @@ -153,7 +169,6 @@ def test_group_users_list_post_duplicate(self): response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 409) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_list_post_invalid_resources(self): test_uri = self.base_groups_uri + '/1239878976' test_uri = test_uri + '/users' @@ -161,7 +176,6 @@ def test_group_users_list_post_invalid_resources(self): response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_detail_get(self): local_username = self.test_username + str(randint(11, 99)) data = {'email': self.test_email, 'username': local_username, 'password': self.test_password} @@ -184,7 +198,6 @@ def test_group_users_detail_get(self): self.assertEqual(response.data['group_id'], group_id) self.assertEqual(response.data['user_id'], user_id) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_detail_delete(self): local_username = self.test_username + str(randint(11, 99)) data = {'email': self.test_email, 'username': local_username, 'password': self.test_password} @@ -205,13 +218,11 @@ def test_group_users_detail_delete(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_detail_delete_invalid_group(self): test_uri = self.base_groups_uri + '/123987102/users/123124' response = self.do_delete(test_uri) self.assertEqual(response.status_code, 204) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_detail_delete_invalid_user(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -220,7 +231,6 @@ def test_group_users_detail_delete_invalid_user(self): response = self.do_delete(test_uri) self.assertEqual(response.status_code, 204) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_users_detail_get_undefined(self): local_username = self.test_username + str(randint(11, 99)) data = {'email': self.test_email, 'username': local_username, 'password': self.test_password} @@ -233,7 +243,6 @@ def test_group_users_detail_get_undefined(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_post_hierarchical(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -256,7 +265,6 @@ def test_group_groups_list_post_hierarchical(self): self.assertEqual(response.data['group_id'], str(group_id)) self.assertEqual(response.data['relationship_type'], relationship_type) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_post_linked(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -279,7 +287,6 @@ def test_group_groups_list_post_linked(self): self.assertEqual(response.data['group_id'], str(group_id)) self.assertEqual(response.data['relationship_type'], relationship_type) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_post_linked_duplicate(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -300,7 +307,6 @@ def test_group_groups_list_post_linked_duplicate(self): # Duplicate responses are idemnotent in this case self.assertEqual(response.status_code, 201) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_post_invalid_group(self): test_uri = self.base_groups_uri + '/123098/groups' relationship_type = 'g' # Graph @@ -308,7 +314,6 @@ def test_group_groups_list_post_invalid_group(self): response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_post_invalid_relationship_type(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -326,7 +331,6 @@ def test_group_groups_list_post_invalid_relationship_type(self): response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 406) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_get(self): data = {'name': 'Bravo Group'} bravo_response = self.do_post(self.base_groups_uri, data) @@ -376,13 +380,11 @@ def test_group_groups_list_get(self): self.assertGreater(len(relationship['uri']), 0) self.assertEqual(relationship_count, len(group_idlist)) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_list_get_notfound(self): test_uri = self.base_groups_uri + '/213213123/groups' response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_get_hierarchical(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -410,7 +412,6 @@ def test_group_groups_detail_get_hierarchical(self): self.assertEqual(response.data['to_group_id'], str(delta_group_id)) self.assertEqual(response.data['relationship_type'], relationship_type) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_get_linked(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -441,7 +442,6 @@ def test_group_groups_detail_get_linked(self): self.assertEqual(response.data['to_group_id'], str(delta_group_id)) self.assertEqual(response.data['relationship_type'], relationship_type) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_get_notfound(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -450,7 +450,6 @@ def test_group_groups_detail_get_notfound(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_delete_hierarchical(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -482,7 +481,6 @@ def test_group_groups_detail_delete_hierarchical(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_delete_linked(self): data = {'name': 'Alpha Group'} alpha_response = self.do_post(self.base_groups_uri, data) @@ -512,13 +510,11 @@ def test_group_groups_detail_delete_linked(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_groups_detail_delete_invalid(self): test_uri = self.base_groups_uri + '/1231234232/groups/1' response = self.do_delete(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_list_post(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -533,7 +529,6 @@ def test_group_courses_list_post(self): self.assertEqual(response.data['group_id'], str(group_id)) self.assertEqual(response.data['course_id'], self.test_course_id) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_list_post_duplicate(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -546,14 +541,12 @@ def test_group_courses_list_post_duplicate(self): response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 409) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_list_post_invalid_resources(self): test_uri = self.base_groups_uri + '/1239878976/courses' data = {'course_id': "98723896"} response = self.do_post(test_uri, data) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_detail_get(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -576,7 +569,6 @@ def test_group_courses_detail_get(self): self.assertEqual(response.data['group_id'], group_id) self.assertEqual(response.data['course_id'], self.test_course_id) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_detail_delete(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -593,13 +585,11 @@ def test_group_courses_detail_delete(self): response = self.do_get(test_uri) self.assertEqual(response.status_code, 404) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_detail_delete_invalid_group(self): test_uri = self.base_groups_uri + '/123987102/courses/123124' response = self.do_delete(test_uri) self.assertEqual(response.status_code, 204) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_detail_delete_invalid_course(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) @@ -608,7 +598,6 @@ def test_group_courses_detail_delete_invalid_course(self): response = self.do_delete(test_uri) self.assertEqual(response.status_code, 204) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_group_courses_detail_get_undefined(self): data = {'name': self.test_group_name} response = self.do_post(self.base_groups_uri, data) From c8e1dbbc7787a1a554e6e4512df96ac6cb2ec0fc Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 21 Apr 2014 22:04:54 -0400 Subject: [PATCH 2/2] add queryable group lists --- lms/djangoapps/api_manager/groups_views.py | 93 ++++++++++++------- ...ursegrouprelationship__add_groupprofile.py | 91 ++++++++++++++++++ .../api_manager/tests/test_groups_views.py | 49 +++++++++- 3 files changed, 198 insertions(+), 35 deletions(-) create mode 100644 lms/djangoapps/api_manager/migrations/0002_auto__add_coursegrouprelationship__add_groupprofile.py diff --git a/lms/djangoapps/api_manager/groups_views.py b/lms/djangoapps/api_manager/groups_views.py index 2bf7ec2a6490..95c64140fb94 100644 --- a/lms/djangoapps/api_manager/groups_views.py +++ b/lms/djangoapps/api_manager/groups_views.py @@ -1,6 +1,7 @@ """ API implementation for group-oriented interactions. """ import uuid import json +from collections import OrderedDict from django.contrib.auth.models import Group, User from django.core.exceptions import ObjectDoesNotExist @@ -33,56 +34,73 @@ def _generate_base_uri(request): return resource_uri -@api_view(['POST']) +@api_view(['GET', 'POST']) @permission_classes((ApiKeyHeaderPermission,)) def group_list(request): """ + GET retrieves a list of groups in the system filtered by type POST creates a new group in the system """ - response_data = {} - base_uri = _generate_base_uri(request) - # Group name must be unique, but we need to support dupes - group = Group.objects.create(name=str(uuid.uuid4())) - original_group_name = request.DATA['name'] + if request.method == 'GET': + if not 'type' in request.GET: + return Response({}, status=status.HTTP_400_BAD_REQUEST) - group.name = '{:04d}: {}'.format(group.id, original_group_name) - group.record_active = True - group.record_date_created = timezone.now() - group.record_date_modified = timezone.now() - group.save() + response_data = [] + profiles = GroupProfile.objects.filter(group_type=request.GET['type']) + for profile in profiles: + item_data = OrderedDict() + item_data['group_id'] = profile.group_id + item_data['group_type'] = profile.group_type + item_data['data'] = json.loads(profile.data) + response_data.append(item_data) - # Relationship model also allows us to use duplicate names - GroupRelationship.objects.create(name=original_group_name, group_id=group.id, parent_group=None) + return Response(response_data) + elif request.method == 'POST': + response_data = {} + base_uri = _generate_base_uri(request) + # Group name must be unique, but we need to support dupes + group = Group.objects.create(name=str(uuid.uuid4())) + original_group_name = request.DATA['name'] - # allow for optional meta information about groups, this will end up in the GroupProfile table - group_type = request.DATA.get('group_type') - data = request.DATA.get('data') + group.name = '{:04d}: {}'.format(group.id, original_group_name) + group.record_active = True + group.record_date_created = timezone.now() + group.record_date_modified = timezone.now() + group.save() - if group_type or data: - profile, _ = GroupProfile.objects.get_or_create(group_id=group.id, group_type=group_type, data=data) + # Relationship model also allows us to use duplicate names + GroupRelationship.objects.create(name=original_group_name, group_id=group.id, parent_group=None) - response_data = {'id': group.id, 'name': original_group_name} - base_uri = _generate_base_uri(request) - response_data['uri'] = '{}/{}'.format(base_uri, group.id) - response_status = status.HTTP_201_CREATED - return Response(response_data, status=response_status) + # allow for optional meta information about groups, this will end up in the GroupProfile table + group_type = request.DATA.get('group_type') + data = request.DATA.get('data') + + if group_type or data: + profile, _ = GroupProfile.objects.get_or_create(group_id=group.id, group_type=group_type, data=data) + + response_data = {'id': group.id, 'name': original_group_name} + base_uri = _generate_base_uri(request) + response_data['uri'] = '{}/{}'.format(base_uri, group.id) + response_status = status.HTTP_201_CREATED + return Response(response_data, status=response_status) -@api_view(['GET']) +@api_view(['GET', 'POST']) @permission_classes((ApiKeyHeaderPermission,)) def group_detail(request, group_id): """ GET retrieves an existing group from the system """ + response_data = {} base_uri = _generate_base_uri(request) try: existing_group = Group.objects.get(id=group_id) existing_group_relationship = GroupRelationship.objects.get(group_id=group_id) except ObjectDoesNotExist: - existing_group = None - existing_group_relationship = None - if existing_group and existing_group_relationship: + return Response({}, status.HTTP_404_NOT_FOUND) + + if request.method == 'GET': response_data['name'] = existing_group_relationship.name response_data['id'] = existing_group.id response_data['uri'] = base_uri @@ -99,15 +117,28 @@ def group_detail(request, group_id): response_data['group_type'] = existing_group_profile.group_type data = existing_group_profile.data if data: - print '******* data = {0}'.format(data) response_data['data'] = json.loads(data) except ObjectDoesNotExist: pass response_status = status.HTTP_200_OK - else: - response_status = status.HTTP_404_NOT_FOUND - return Response(response_data, status=response_status) + + return Response(response_data, status=response_status) + elif request.method == 'POST': + # update GroupProfile data + + group_type = request.DATA.get('group_type') + data = request.DATA.get('data') + + if not group_type and not data: + return Response({}, status.HTTP_400_BAD_REQUEST) + + profile, _ = GroupProfile.objects.get_or_create(group_id=group_id) + profile.group_type = group_type + profile.data = data + profile.save() + + return Response({}) @api_view(['POST']) diff --git a/lms/djangoapps/api_manager/migrations/0002_auto__add_coursegrouprelationship__add_groupprofile.py b/lms/djangoapps/api_manager/migrations/0002_auto__add_coursegrouprelationship__add_groupprofile.py new file mode 100644 index 000000000000..976d775f5466 --- /dev/null +++ b/lms/djangoapps/api_manager/migrations/0002_auto__add_coursegrouprelationship__add_groupprofile.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'CourseGroupRelationship' + db.create_table('api_manager_coursegrouprelationship', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('course_id', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.Group'])), + )) + db.send_create_signal('api_manager', ['CourseGroupRelationship']) + + # Adding model 'GroupProfile' + db.create_table('auth_groupprofile', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.Group'])), + ('group_type', self.gf('django.db.models.fields.CharField')(max_length=32, null=True, db_index=True)), + ('data', self.gf('django.db.models.fields.TextField')(blank=True)), + )) + db.send_create_signal('api_manager', ['GroupProfile']) + + + def backwards(self, orm): + # Deleting model 'CourseGroupRelationship' + db.delete_table('api_manager_coursegrouprelationship') + + # Deleting model 'GroupProfile' + db.delete_table('auth_groupprofile') + + + models = { + 'api_manager.coursegrouprelationship': { + 'Meta': {'object_name': 'CourseGroupRelationship'}, + 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'api_manager.groupprofile': { + 'Meta': {'object_name': 'GroupProfile', 'db_table': "'auth_groupprofile'"}, + 'data': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']"}), + 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'api_manager.grouprelationship': { + 'Meta': {'object_name': 'GroupRelationship'}, + 'group': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.Group']", 'unique': 'True', 'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'parent_group': ('django.db.models.fields.related.ForeignKey', [], {'default': '0', 'related_name': "'child_groups'", 'null': 'True', 'blank': 'True', 'to': "orm['api_manager.GroupRelationship']"}), + 'record_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'record_date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 4, 21, 0, 0)'}), + 'record_date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'api_manager.linkedgrouprelationship': { + 'Meta': {'object_name': 'LinkedGroupRelationship'}, + 'from_group_relationship': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'from_group_relationships'", 'to': "orm['api_manager.GroupRelationship']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'record_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'record_date_created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2014, 4, 21, 0, 0)'}), + 'record_date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'to_group_relationship': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_group_relationships'", 'to': "orm['api_manager.GroupRelationship']"}) + }, + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['api_manager'] \ No newline at end of file diff --git a/lms/djangoapps/api_manager/tests/test_groups_views.py b/lms/djangoapps/api_manager/tests/test_groups_views.py index 67d007813cab..42d5d44058f3 100644 --- a/lms/djangoapps/api_manager/tests/test_groups_views.py +++ b/lms/djangoapps/api_manager/tests/test_groups_views.py @@ -5,18 +5,16 @@ rake fasttest_lms[common/djangoapps/api_manager/tests/test_group_views.py] """ from random import randint -import unittest import uuid import json -from django.conf import settings from django.core.cache import cache from django.test import TestCase, Client from django.test.utils import override_settings from api_manager.models import GroupRelationship from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore.tests.factories import CourseFactory TEST_API_KEY = str(uuid.uuid4()) @@ -119,6 +117,21 @@ def test_group_list_get_with_profile(self): self.assertGreater(response.data['id'], 0) group_id = response.data['id'] + # query for list of groups, but don't put the type filter (bad) + test_uri = self.base_groups_uri + response = self.do_get(test_uri) + self.assertEqual(response.status_code, 400) + + # try again with filter + test_uri = self.base_groups_uri + '?type=series' + response = self.do_get(test_uri) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['group_id'], group_id) + self.assertEqual(response.data[0]['group_type'], 'series') + self.assertEqual(response.data[0]['data']['display_name'], 'My first series') + + # query the group detail test_uri = self.base_groups_uri + '/' + str(group_id) response = self.do_get(test_uri) self.assertEqual(response.status_code, 200) @@ -127,7 +140,35 @@ def test_group_list_get_with_profile(self): self.assertEqual(response.data['uri'], confirm_uri) self.assertEqual(response.data['name'], self.test_group_name) self.assertEqual(response.data['group_type'], 'series') - self.assertEqual(response.data['data']['display_name'],'My first series') + self.assertEqual(response.data['data']['display_name'], 'My first series') + + # update the profile + + # first with missing data + response = self.do_post(test_uri, {}) + self.assertEqual(response.status_code, 400) + + data = { + 'name': self.test_group_name, + 'group_type': 'seriesX', + 'data': json.dumps({'display_name': 'My updated series'}) + } + response = self.do_post(test_uri, data) + self.assertEqual(response.status_code, 200) + + # requery the filter + test_uri = self.base_groups_uri + '?type=series' + response = self.do_get(test_uri) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 0) + + test_uri = self.base_groups_uri + '?type=seriesX' + response = self.do_get(test_uri) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['group_id'], group_id) + self.assertEqual(response.data[0]['group_type'], 'seriesX') + self.assertEqual(response.data[0]['data']['display_name'], 'My updated series') def test_group_detail_get_undefined(self): test_uri = self.base_groups_uri + '/123456789'