Commit 610710cf by Christina Roberts

Merge pull request #5133 from edx/christina/cohorts-api

Create auto cohorts when list_cohorts is called.
parents dedd88cc 020094b8
......@@ -160,19 +160,30 @@ def get_cohort(user, course_key):
return group
def get_course_cohorts(course_key):
def get_course_cohorts(course):
"""
Get a list of all the cohorts in the given course.
Get a list of all the cohorts in the given course. This will include auto cohorts,
regardless of whether or not the auto cohorts include any users.
Arguments:
course_key: CourseKey
course: the course for which cohorts should be returned
Returns:
A list of CourseUserGroup objects. Empty if there are no cohorts. Does
not check whether the course is cohorted.
"""
# TODO: remove auto_cohort check with TNL-160
if course.auto_cohort:
# Ensure all auto cohorts are created.
for group_name in course.auto_cohort_groups:
CourseUserGroup.objects.get_or_create(
course_id=course.location.course_key,
group_type=CourseUserGroup.COHORT,
name=group_name
)
return list(CourseUserGroup.objects.filter(
course_id=course_key,
course_id=course.location.course_key,
group_type=CourseUserGroup.COHORT
))
......@@ -269,13 +280,6 @@ def add_user_to_cohort(cohort, username_or_email):
return (user, previous_cohort)
def get_course_cohort_names(course_key):
"""
Return a list of the cohort names in a course.
"""
return [c.name for c in get_course_cohorts(course_key)]
def delete_empty_cohort(course_key, name):
"""
Remove an empty cohort. Raise ValueError if cohort is not empty.
......
"""
Helper methods for testing cohorts.
"""
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum
def topic_name_to_id(course, name):
"""
Given a discussion topic name, return an id for that name (includes
course and url_name).
"""
return "{course}_{run}_{name}".format(
course=course.location.course,
run=course.url_name,
name=name
)
def config_course_cohorts(course, discussions,
cohorted,
cohorted_discussions=None,
auto_cohort=None,
auto_cohort_groups=None):
"""
Given a course with no discussion set up, add the discussions and set
the cohort config appropriately.
Arguments:
course: CourseDescriptor
discussions: list of topic names strings. Picks ids and sort_keys
automatically.
cohorted: bool.
cohorted_discussions: optional list of topic names. If specified,
converts them to use the same ids as topic names.
auto_cohort: optional bool.
auto_cohort_groups: optional list of strings
(names of groups to put students into).
Returns:
Nothing -- modifies course in place.
"""
def to_id(name):
return topic_name_to_id(course, name)
topics = dict((name, {"sort_key": "A",
"id": to_id(name)})
for name in discussions)
course.discussion_topics = topics
d = {"cohorted": cohorted}
if cohorted_discussions is not None:
d["cohorted_discussions"] = [to_id(name)
for name in cohorted_discussions]
if auto_cohort is not None:
d["auto_cohort"] = auto_cohort
if auto_cohort_groups is not None:
d["auto_cohort_groups"] = auto_cohort_groups
course.cohort_config = d
try:
# Not implemented for XMLModulestore, which is used by test_cohorts.
modulestore().update_item(course, ModuleStoreEnum.UserID.test)
except NotImplementedError:
pass
......@@ -4,6 +4,8 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings
from factory import post_generation, Sequence
from factory.django import DjangoModelFactory
from course_groups.tests.helpers import config_course_cohorts
from collections import namedtuple
from django.http import Http404
from django.contrib.auth.models import User
......@@ -123,11 +125,19 @@ class ListCohortsTestCase(CohortViewsTestCase):
self.assertItemsEqual(
response_dict.get("cohorts"),
[
{"name": cohort.name, "id": cohort.id}
{"name": cohort.name, "id": cohort.id, "user_count": cohort.user_count}
for cohort in expected_cohorts
]
)
@staticmethod
def create_expected_cohort(cohort, user_count):
"""
Create a tuple storing the expected cohort information.
"""
cohort_tuple = namedtuple("Cohort", "name id user_count")
return cohort_tuple(name=cohort.name, id=cohort.id, user_count=user_count)
def test_non_staff(self):
"""
Verify that we cannot access list_cohorts if we're a non-staff user.
......@@ -145,12 +155,44 @@ class ListCohortsTestCase(CohortViewsTestCase):
Verify that cohorts are in response for a course with some cohorts.
"""
self._create_cohorts()
expected_cohorts = CourseUserGroup.objects.filter(
course_id=self.course.id,
group_type=CourseUserGroup.COHORT
)
expected_cohorts = [
ListCohortsTestCase.create_expected_cohort(self.cohort1, 3),
ListCohortsTestCase.create_expected_cohort(self.cohort2, 2),
ListCohortsTestCase.create_expected_cohort(self.cohort3, 2),
]
self.verify_lists_expected_cohorts(self.request_list_cohorts(self.course), expected_cohorts)
def test_auto_cohorts(self):
"""
Verify that auto cohorts are included in the response.
"""
config_course_cohorts(self.course, [], cohorted=True, auto_cohort=True,
auto_cohort_groups=["AutoGroup1", "AutoGroup2"])
# Will create cohort1, cohort2, and cohort3. Auto cohorts remain uncreated.
self._create_cohorts()
# Get the cohorts from the course, which will cause auto cohorts to be created.
actual_cohorts = self.request_list_cohorts(self.course)
# Get references to the created auto cohorts.
auto_cohort_1 = CourseUserGroup.objects.get(
course_id=self.course.location.course_key,
group_type=CourseUserGroup.COHORT,
name="AutoGroup1"
)
auto_cohort_2 = CourseUserGroup.objects.get(
course_id=self.course.location.course_key,
group_type=CourseUserGroup.COHORT,
name="AutoGroup2"
)
expected_cohorts = [
ListCohortsTestCase.create_expected_cohort(self.cohort1, 3),
ListCohortsTestCase.create_expected_cohort(self.cohort2, 2),
ListCohortsTestCase.create_expected_cohort(self.cohort3, 2),
ListCohortsTestCase.create_expected_cohort(auto_cohort_1, 0),
ListCohortsTestCase.create_expected_cohort(auto_cohort_2, 0),
]
self.verify_lists_expected_cohorts(actual_cohorts, expected_cohorts)
class AddCohortTestCase(CohortViewsTestCase):
"""
......
......@@ -46,10 +46,10 @@ def list_cohorts(request, course_key_string):
# this is a string when we get it here
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_key_string)
get_course_with_access(request.user, 'staff', course_key)
course = get_course_with_access(request.user, 'staff', course_key)
all_cohorts = [{'name': c.name, 'id': c.id}
for c in cohorts.get_course_cohorts(course_key)]
all_cohorts = [{'name': c.name, 'id': c.id, 'user_count': c.users.count()}
for c in cohorts.get_course_cohorts(course)]
return json_http_response({'success': True,
'cohorts': all_cohorts})
......
......@@ -11,8 +11,7 @@ import newrelic.agent
from edxmako.shortcuts import render_to_response
from courseware.courses import get_course_with_access
from course_groups.cohorts import (is_course_cohorted, get_cohort_id, is_commentable_cohorted,
get_cohorted_commentables, get_course_cohorts, get_cohort_by_id)
from course_groups.cohorts import is_course_cohorted, get_cohort_id, get_course_cohorts, is_commentable_cohorted
from courseware.access import has_access
from django_comment_client.permissions import cached_has_permission
......@@ -52,7 +51,7 @@ def make_course_settings(course, include_category_map=False):
'is_cohorted': is_course_cohorted(course.id),
'allow_anonymous': course.allow_anonymous,
'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
'cohorts': [{"id": str(g.id), "name": g.name} for g in get_course_cohorts(course.id)],
'cohorts': [{"id": str(g.id), "name": g.name} for g in get_course_cohorts(course)],
}
if include_category_map:
......
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