Commit ab0591d6 by Zia Fazal Committed by Jonathan Piacenti

initial changes

completed tests and added type filter

removed organizations app

migration to delete tables
parent 9732f151
# -*- 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):
# Deleting model 'Organization'
db.delete_table('api_manager_organization')
# Removing M2M table for field users on 'Organization'
db.delete_table('api_manager_organization_users')
# Removing M2M table for field groups on 'Organization'
db.delete_table('api_manager_organization_groups')
# Removing M2M table for field workgroups on 'Organization'
db.delete_table('api_manager_organization_workgroups')
def backwards(self, orm):
# Adding model 'Organization'
db.create_table('api_manager_organization', (
('contact_email', self.gf('django.db.models.fields.EmailField')(max_length=255, null=True, blank=True)),
('contact_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('display_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
('created', self.gf('model_utils.fields.AutoCreatedField')(default=datetime.datetime.now)),
('modified', self.gf('model_utils.fields.AutoLastModifiedField')(default=datetime.datetime.now)),
('logo_url', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
('contact_phone', self.gf('django.db.models.fields.CharField')(max_length=50, null=True, blank=True)),
))
db.send_create_signal('api_manager', ['Organization'])
# Adding M2M table for field users on 'Organization'
db.create_table('api_manager_organization_users', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('organization', models.ForeignKey(orm['api_manager.organization'], null=False)),
('user', models.ForeignKey(orm['auth.user'], null=False))
))
db.create_unique('api_manager_organization_users', ['organization_id', 'user_id'])
# Adding M2M table for field groups on 'Organization'
db.create_table('api_manager_organization_groups', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('organization', models.ForeignKey(orm['api_manager.organization'], null=False)),
('group', models.ForeignKey(orm['auth.group'], null=False))
))
db.create_unique('api_manager_organization_groups', ['organization_id', 'group_id'])
# Adding M2M table for field workgroups on 'Organization'
db.create_table('api_manager_organization_workgroups', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('organization', models.ForeignKey(orm['api_manager.organization'], null=False)),
('workgroup', models.ForeignKey(orm['projects.workgroup'], null=False))
))
db.create_unique('api_manager_organization_workgroups', ['organization_id', 'workgroup_id'])
models = {
'api_manager.coursecontentgrouprelationship': {
'Meta': {'unique_together': "(('course_id', 'content_id', 'group_profile'),)", 'object_name': 'CourseContentGroupRelationship'},
'content_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'group_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['api_manager.GroupProfile']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'record_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'api_manager.coursegrouprelationship': {
'Meta': {'object_name': 'CourseGroupRelationship'},
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'record_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'api_manager.coursemodulecompletion': {
'Meta': {'object_name': 'CourseModuleCompletion'},
'content_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'stage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'course_completions'", 'to': "orm['auth.User']"})
},
'api_manager.groupprofile': {
'Meta': {'object_name': 'GroupProfile', 'db_table': "'auth_groupprofile'"},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'group': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.Group']", 'unique': 'True'}),
'group_type': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'record_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'api_manager.grouprelationship': {
'Meta': {'object_name': 'GroupRelationship'},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'group': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.Group']", 'unique': 'True', 'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'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'})
},
'api_manager.linkedgrouprelationship': {
'Meta': {'object_name': 'LinkedGroupRelationship'},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'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'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'record_active': ('django.db.models.fields.BooleanField', [], {'default': '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'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'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
# pylint: disable=C0103
""" ORGANIZATIONS API VIEWS """
from django.conf import settings
from django.contrib.auth.models import User, Group
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Sum, F, Count
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from api_manager.courseware_access import get_course_key
from organizations.models import Organization
from api_manager.users.serializers import UserSerializer, SimpleUserSerializer
from api_manager.groups.serializers import GroupSerializer
from api_manager.utils import str2bool
from gradebook.models import StudentGradebook
from student.models import CourseEnrollment
from student.roles import get_aggregate_exclusion_user_ids
from .serializers import OrganizationSerializer
class OrganizationsViewSet(viewsets.ModelViewSet):
"""
Django Rest Framework ViewSet for the Organization model.
"""
serializer_class = OrganizationSerializer
model = Organization
@action(methods=['get', ])
def metrics(self, request, pk):
"""
Provide statistical information for the specified Organization
"""
response_data = {}
grade_avg = 0
grade_complete_match_range = getattr(settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
org_user_grades = StudentGradebook.objects.filter(user__organizations=pk, user__is_active=True)
courses_filter = request.QUERY_PARAMS.get('courses', None)
courses = []
exclude_users = set()
if courses_filter:
upper_bound = getattr(settings, 'API_LOOKUP_UPPER_BOUND', 100)
courses_filter = courses_filter.split(",")[:upper_bound]
for course_string in courses_filter:
courses.append(get_course_key(course_string))
# fill exclude users
for course_key in courses:
exclude_users.union(get_aggregate_exclusion_user_ids(course_key))
org_user_grades = org_user_grades.filter(course_id__in=courses).exclude(user_id__in=exclude_users)
users_grade_sum = org_user_grades.aggregate(Sum('grade'))
if users_grade_sum['grade__sum']:
users_enrolled_qs = CourseEnrollment.objects.filter(user__is_active=True, is_active=True,
user__organizations=pk)\
.exclude(user_id__in=exclude_users)
if courses:
users_enrolled_qs = users_enrolled_qs.filter(course_id__in=courses)
users_enrolled = users_enrolled_qs.aggregate(Count('user', distinct=True))
total_users = users_enrolled['user__count']
if total_users:
# in order to compute avg across organization we need course of courses org has
total_courses_in_org = len(courses)
if not courses:
org_courses = users_enrolled_qs.aggregate(Count('course_id', distinct=True))
total_courses_in_org = org_courses['course_id__count']
grade_avg = float('{0:.3f}'.format(
float(users_grade_sum['grade__sum']) / total_users / total_courses_in_org
))
response_data['users_grade_average'] = grade_avg
users_grade_complete_count = org_user_grades\
.filter(proforma_grade__lte=F('grade') + grade_complete_match_range, proforma_grade__gt=0)\
.aggregate(Count('user', distinct=True))
response_data['users_grade_complete_count'] = users_grade_complete_count['user__count'] or 0
return Response(response_data, status=status.HTTP_200_OK)
@action(methods=['get', 'post'])
def users(self, request, pk):
"""
- URI: ```/api/organizations/{org_id}/users/```
- GET: Returns users in an organization
* course_id parameter should filter user by course
* include_course_counts parameter should be `true` to get user's enrollment count
* include_grades parameter should be `true` to get user's grades
* for the course given in the course_id parameter
- POST: Adds a User to an Organization
"""
if request.method == 'GET':
include_course_counts = request.QUERY_PARAMS.get('include_course_counts', None)
include_grades = request.QUERY_PARAMS.get('include_grades', None)
course_id = request.QUERY_PARAMS.get('course_id', None)
grade_complete_match_range = getattr(settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
course_key = None
if course_id:
course_key = get_course_key(course_id)
users = User.objects.filter(organizations=pk)
if course_key:
users = users.filter(courseenrollment__course_id__exact=course_key,
courseenrollment__is_active=True)
if str2bool(include_grades):
users = users.select_related('studentgradebook')
if str2bool(include_course_counts):
enrollments = CourseEnrollment.objects.filter(user__in=users).values('user').order_by().annotate(total=Count('user'))
enrollments_by_user = {}
for enrollment in enrollments:
enrollments_by_user[enrollment['user']] = enrollment['total']
response_data = []
if users:
for user in users:
serializer = SimpleUserSerializer(user)
user_data = serializer.data
if str2bool(include_course_counts):
user_data['course_count'] = enrollments_by_user.get(user.id, 0)
if str2bool(include_grades) and course_key:
user_grades = {'grade': 0, 'proforma_grade': 0, 'complete_status': False}
gradebook = user.studentgradebook_set.filter(course_id=course_key)
if gradebook:
user_grades['grade'] = gradebook[0].grade
user_grades['proforma_grade'] = gradebook[0].proforma_grade
user_grades['complete_status'] = True if 0 < gradebook[0].proforma_grade <= \
gradebook[0].grade + grade_complete_match_range else False
user_data.update(user_grades)
response_data.append(user_data)
return Response(response_data, status=status.HTTP_200_OK)
else:
user_id = request.DATA.get('id')
try:
user = User.objects.get(id=user_id)
except ObjectDoesNotExist:
message = 'User {} does not exist'.format(user_id)
return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)
organization = self.get_object()
organization.users.add(user)
organization.save()
return Response({}, status=status.HTTP_201_CREATED)
@action(methods=['get', 'post'])
def groups(self, request, pk):
"""
Add a Group to a organization or retrieve list of groups in organization
"""
if request.method == 'GET':
group_type = request.QUERY_PARAMS.get('type', None)
groups = Group.objects.filter(organizations=pk)
if group_type:
groups = groups.filter(groupprofile__group_type=group_type)
response_data = []
if groups:
for group in groups:
serializer = GroupSerializer(group)
response_data.append(serializer.data) # pylint: disable=E1101
return Response(response_data, status=status.HTTP_200_OK)
else:
group_id = request.DATA.get('id')
try:
group = Group.objects.get(id=group_id)
except ObjectDoesNotExist:
message = 'Group {} does not exist'.format(group_id)
return Response({"detail": message}, status.HTTP_400_BAD_REQUEST)
organization = self.get_object()
organization.groups.add(group)
organization.save()
return Response({}, status=status.HTTP_201_CREATED)
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