diff --git a/.gitignore b/.gitignore
index 69d98d7db8..b166d2719f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,8 @@ jscover.log
jscover.log.*
.tddium*
common/test/data/test_unicode/static/
+django-pyfs
+test_root/uploads/*.txt
### Installation artifacts
*.egg-info
diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py
index 584a4820c0..c041f72f5b 100644
--- a/cms/djangoapps/contentstore/tests/test_course_settings.py
+++ b/cms/djangoapps/contentstore/tests/test_course_settings.py
@@ -139,6 +139,100 @@ class CourseDetailsTestCase(CourseTestCase):
self.assertNotContains(response, "Course Introduction Video")
self.assertNotContains(response, "Requirements")
+ def _seed_milestone_relationship_types(self):
+ """
+ Helper method to prepopulate MRTs so the tests can run
+ Note the settings check -- exams feature must be enabled for the tests to run correctly
+ """
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ from milestones.models import MilestoneRelationshipType
+ MilestoneRelationshipType.objects.create(name='requires')
+ MilestoneRelationshipType.objects.create(name='fulfills')
+
+ @patch.dict(settings.FEATURES, {'ENTRANCE_EXAMS': True})
+ def test_entrance_exam_created_and_deleted_successfully(self):
+ self._seed_milestone_relationship_types()
+ settings_details_url = get_url(self.course.id)
+ data = {
+ 'entrance_exam_enabled': 'true',
+ 'entrance_exam_minimum_score_pct': '60',
+ 'syllabus': 'none',
+ 'short_description': 'empty',
+ 'overview': '',
+ 'effort': '',
+ 'intro_video': ''
+ }
+ response = self.client.post(settings_details_url, data=json.dumps(data), content_type='application/json',
+ HTTP_ACCEPT='application/json')
+ self.assertEquals(response.status_code, 200)
+ course = modulestore().get_course(self.course.id)
+ self.assertTrue(course.entrance_exam_enabled)
+ self.assertEquals(course.entrance_exam_minimum_score_pct, .60)
+
+ # Delete the entrance exam
+ data['entrance_exam_enabled'] = "false"
+ response = self.client.post(
+ settings_details_url,
+ data=json.dumps(data),
+ content_type='application/json',
+ HTTP_ACCEPT='application/json'
+ )
+ course = modulestore().get_course(self.course.id)
+ self.assertEquals(response.status_code, 200)
+ self.assertFalse(course.entrance_exam_enabled)
+ self.assertEquals(course.entrance_exam_minimum_score_pct, None)
+
+ @patch.dict(settings.FEATURES, {'ENTRANCE_EXAMS': True})
+ def test_entrance_exam_store_default_min_score(self):
+ """
+ test that creating an entrance exam should store the default value, if key missing in json request
+ or entrance_exam_minimum_score_pct is an empty string
+ """
+ self._seed_milestone_relationship_types()
+ settings_details_url = get_url(self.course.id)
+ test_data_1 = {
+ 'entrance_exam_enabled': 'true',
+ 'syllabus': 'none',
+ 'short_description': 'empty',
+ 'overview': '',
+ 'effort': '',
+ 'intro_video': ''
+ }
+ response = self.client.post(
+ settings_details_url,
+ data=json.dumps(test_data_1),
+ content_type='application/json',
+ HTTP_ACCEPT='application/json'
+ )
+ self.assertEquals(response.status_code, 200)
+ course = modulestore().get_course(self.course.id)
+ self.assertTrue(course.entrance_exam_enabled)
+
+ # entrance_exam_minimum_score_pct is not present in the request so default value should be saved.
+ self.assertEquals(course.entrance_exam_minimum_score_pct, .5)
+
+ #add entrance_exam_minimum_score_pct with empty value in json request.
+ test_data_2 = {
+ 'entrance_exam_enabled': 'true',
+ 'entrance_exam_minimum_score_pct': '',
+ 'syllabus': 'none',
+ 'short_description': 'empty',
+ 'overview': '',
+ 'effort': '',
+ 'intro_video': ''
+ }
+
+ response = self.client.post(
+ settings_details_url,
+ data=json.dumps(test_data_2),
+ content_type='application/json',
+ HTTP_ACCEPT='application/json'
+ )
+ self.assertEquals(response.status_code, 200)
+ course = modulestore().get_course(self.course.id)
+ self.assertTrue(course.entrance_exam_enabled)
+ self.assertEquals(course.entrance_exam_minimum_score_pct, .5)
+
def test_editable_short_description_fetch(self):
settings_details_url = get_url(self.course.id)
diff --git a/cms/djangoapps/contentstore/views/__init__.py b/cms/djangoapps/contentstore/views/__init__.py
index 9cceccd6e6..2f582ef498 100644
--- a/cms/djangoapps/contentstore/views/__init__.py
+++ b/cms/djangoapps/contentstore/views/__init__.py
@@ -8,6 +8,7 @@ from .assets import *
from .checklist import *
from .component import *
from .course import *
+from .entrance_exam import *
from .error import *
from .helpers import *
from .item import *
diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py
index e13f1f1a87..ecf18c2f64 100644
--- a/cms/djangoapps/contentstore/views/course.py
+++ b/cms/djangoapps/contentstore/views/course.py
@@ -60,6 +60,8 @@ from .component import (
ADVANCED_COMPONENT_TYPES,
)
from contentstore.tasks import rerun_course
+from contentstore.views.entrance_exam import create_entrance_exam, delete_entrance_exam
+
from .library import LIBRARIES_ENABLED
from .item import create_xblock_info
from course_creators.views import get_course_creator_status, add_user_with_status_unrequested
@@ -824,7 +826,8 @@ def settings_handler(request, course_key_string):
'details_url': reverse_course_url('settings_handler', course_key),
'about_page_editable': about_page_editable,
'short_description_editable': short_description_editable,
- 'upload_asset_url': upload_asset_url
+ 'upload_asset_url': upload_asset_url,
+ 'course_handler_url': reverse_course_url('course_handler', course_key),
}
if prerequisite_course_enabled:
courses, in_process_course_actions = get_courses_accessible_to_user(request)
@@ -843,13 +846,40 @@ def settings_handler(request, course_key_string):
# encoder serializes dates, old locations, and instances
encoder=CourseSettingsEncoder
)
- else: # post or put, doesn't matter.
+ # For every other possible method type submitted by the caller...
+ else:
# if pre-requisite course feature is enabled set pre-requisite course
if prerequisite_course_enabled:
prerequisite_course_keys = request.json.get('pre_requisite_courses', [])
if not all(is_valid_course_key(course_key) for course_key in prerequisite_course_keys):
return JsonResponseBadRequest({"error": _("Invalid prerequisite course key")})
set_prerequisite_courses(course_key, prerequisite_course_keys)
+
+ # If the entrance exams feature has been enabled, we'll need to check for some
+ # feature-specific settings and handle them accordingly
+ # We have to be careful that we're only executing the following logic if we actually
+ # need to create or delete an entrance exam from the specified course
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ course_entrance_exam_present = course_module.entrance_exam_enabled
+ entrance_exam_enabled = request.json.get('entrance_exam_enabled', '') == 'true'
+ ee_min_score_pct = request.json.get('entrance_exam_minimum_score_pct', None)
+
+ # If the entrance exam box on the settings screen has been checked,
+ # and the course does not already have an entrance exam attached...
+ if entrance_exam_enabled and not course_entrance_exam_present:
+ # Load the default minimum score threshold from settings, then try to override it
+ entrance_exam_minimum_score_pct = float(settings.ENTRANCE_EXAM_MIN_SCORE_PCT)
+ if ee_min_score_pct and ee_min_score_pct != '':
+ entrance_exam_minimum_score_pct = float(ee_min_score_pct)
+ # Create the entrance exam
+ create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct)
+
+ # If the entrance exam box on the settings screen has been unchecked,
+ # and the course has an entrance exam attached...
+ elif not entrance_exam_enabled and course_entrance_exam_present:
+ delete_entrance_exam(request, course_key)
+
+ # Perform the normal update workflow for the CourseDetails model
return JsonResponse(
CourseDetails.update_from_json(course_key, request.json, request.user),
encoder=CourseSettingsEncoder
diff --git a/cms/djangoapps/contentstore/views/entrance_exam.py b/cms/djangoapps/contentstore/views/entrance_exam.py
new file mode 100644
index 0000000000..caa94a2cc4
--- /dev/null
+++ b/cms/djangoapps/contentstore/views/entrance_exam.py
@@ -0,0 +1,224 @@
+"""
+Entrance Exams view module -- handles all requests related to entrance exam management via Studio
+Intended to be utilized as an AJAX callback handler, versus a proper view/screen
+"""
+import json
+import logging
+
+from django.contrib.auth.decorators import login_required
+from django_future.csrf import ensure_csrf_cookie
+from django.http import HttpResponse
+from django.test import RequestFactory
+
+from contentstore.views.item import create_item, delete_item
+from milestones import api as milestones_api
+from models.settings.course_metadata import CourseMetadata
+from opaque_keys.edx.keys import CourseKey, UsageKey
+from opaque_keys import InvalidKeyError
+from student.auth import has_course_author_access
+from util.milestones_helpers import generate_milestone_namespace, NAMESPACE_CHOICES
+from xmodule.modulestore.django import modulestore
+from xmodule.modulestore.exceptions import ItemNotFoundError
+from django.conf import settings
+
+__all__ = ['entrance_exam', ]
+
+log = logging.getLogger(__name__)
+
+
+@login_required
+@ensure_csrf_cookie
+def entrance_exam(request, course_key_string):
+ """
+ The restful handler for entrance exams.
+ It allows retrieval of all the assets (as an HTML page), as well as uploading new assets,
+ deleting assets, and changing the "locked" state of an asset.
+
+ GET
+ Retrieves the entrance exam module (metadata) for the specified course
+ POST
+ Adds an entrance exam module to the specified course.
+ DELETE
+ Removes the entrance exam from the course
+ """
+ course_key = CourseKey.from_string(course_key_string)
+
+ # Deny access if the user is valid, but they lack the proper object access privileges
+ if not has_course_author_access(request.user, course_key):
+ return HttpResponse(status=403)
+
+ # Retrieve the entrance exam module for the specified course (returns 404 if none found)
+ if request.method == 'GET':
+ return _get_entrance_exam(request, course_key)
+
+ # Create a new entrance exam for the specified course (returns 201 if created)
+ elif request.method == 'POST':
+ response_format = request.REQUEST.get('format', 'html')
+ http_accept = request.META.get('http_accept')
+ if response_format == 'json' or 'application/json' in http_accept:
+ ee_min_score = request.POST.get('entrance_exam_minimum_score_pct', None)
+
+ # if request contains empty value or none then save the default one.
+ entrance_exam_minimum_score_pct = float(settings.ENTRANCE_EXAM_MIN_SCORE_PCT)
+ if ee_min_score != '' and ee_min_score is not None:
+ entrance_exam_minimum_score_pct = float(ee_min_score)
+ return create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct)
+ return HttpResponse(status=400)
+
+ # Remove the entrance exam module for the specified course (returns 204 regardless of existence)
+ elif request.method == 'DELETE':
+ return delete_entrance_exam(request, course_key)
+
+ # No other HTTP verbs/methods are supported at this time
+ else:
+ return HttpResponse(status=405)
+
+
+def create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct):
+ """
+ api method to create an entrance exam.
+ First clean out any old entrance exams.
+ """
+ _delete_entrance_exam(request, course_key)
+ return _create_entrance_exam(
+ request=request,
+ course_key=course_key,
+ entrance_exam_minimum_score_pct=entrance_exam_minimum_score_pct
+ )
+
+
+def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=None):
+ """
+ Internal workflow operation to create an entrance exam
+ """
+ # Provide a default value for the minimum score percent if nothing specified
+ if entrance_exam_minimum_score_pct is None:
+ entrance_exam_minimum_score_pct = float(settings.ENTRANCE_EXAM_MIN_SCORE_PCT)
+
+ # Confirm the course exists
+ course = modulestore().get_course(course_key)
+ if course is None:
+ return HttpResponse(status=400)
+
+ # Create the entrance exam item (currently it's just a chapter)
+ payload = {
+ 'category': "chapter",
+ 'display_name': "Entrance Exam",
+ 'parent_locator': unicode(course.location),
+ 'is_entrance_exam': True,
+ 'in_entrance_exam': True,
+ }
+ factory = RequestFactory()
+ internal_request = factory.post('/', json.dumps(payload), content_type="application/json")
+ internal_request.user = request.user
+ created_item = json.loads(create_item(internal_request).content)
+
+ # Set the entrance exam metadata flags for this course
+ # Reload the course so we don't overwrite the new child reference
+ course = modulestore().get_course(course_key)
+ metadata = {
+ 'entrance_exam_enabled': True,
+ 'entrance_exam_minimum_score_pct': entrance_exam_minimum_score_pct / 100,
+ 'entrance_exam_id': created_item['locator'],
+ }
+ CourseMetadata.update_from_dict(metadata, course, request.user)
+
+ # Add an entrance exam milestone if one does not already exist
+ milestone_namespace = generate_milestone_namespace(
+ NAMESPACE_CHOICES['ENTRANCE_EXAM'],
+ course_key
+ )
+ milestones = milestones_api.get_milestones(milestone_namespace)
+ if len(milestones):
+ milestone = milestones[0]
+ else:
+ description = 'Autogenerated during {} entrance exam creation.'.format(unicode(course.id))
+ milestone = milestones_api.add_milestone({
+ 'name': 'Completed Course Entrance Exam',
+ 'namespace': milestone_namespace,
+ 'description': description
+ })
+ relationship_types = milestones_api.get_milestone_relationship_types()
+ milestones_api.add_course_milestone(
+ unicode(course.id),
+ relationship_types['REQUIRES'],
+ milestone
+ )
+ milestones_api.add_course_content_milestone(
+ unicode(course.id),
+ created_item['locator'],
+ relationship_types['FULFILLS'],
+ milestone
+ )
+
+ return HttpResponse(status=201)
+
+
+def _get_entrance_exam(request, course_key): # pylint: disable=W0613
+ """
+ Internal workflow operation to retrieve an entrance exam
+ """
+ course = modulestore().get_course(course_key)
+ if course is None:
+ return HttpResponse(status=400)
+ if not getattr(course, 'entrance_exam_id'):
+ return HttpResponse(status=404)
+ try:
+ exam_key = UsageKey.from_string(course.entrance_exam_id)
+ except InvalidKeyError:
+ return HttpResponse(status=404)
+ try:
+ exam_descriptor = modulestore().get_item(exam_key)
+ return HttpResponse(
+ _serialize_entrance_exam(exam_descriptor),
+ status=200, mimetype='application/json')
+ except ItemNotFoundError:
+ return HttpResponse(status=404)
+
+
+def delete_entrance_exam(request, course_key):
+ """
+ api method to delete an entrance exam
+ """
+ return _delete_entrance_exam(request=request, course_key=course_key)
+
+
+def _delete_entrance_exam(request, course_key):
+ """
+ Internal workflow operation to remove an entrance exam
+ """
+ store = modulestore()
+ course = store.get_course(course_key)
+ if course is None:
+ return HttpResponse(status=400)
+
+ course_children = store.get_items(
+ course_key,
+ qualifiers={'category': 'chapter'}
+ )
+ for course_child in course_children:
+ if course_child.is_entrance_exam:
+ delete_item(request, course_child.scope_ids.usage_id)
+ milestones_api.remove_content_references(unicode(course_child.scope_ids.usage_id))
+
+ # Reset the entrance exam flags on the course
+ # Reload the course so we have the latest state
+ course = store.get_course(course_key)
+ if getattr(course, 'entrance_exam_id'):
+ metadata = {
+ 'entrance_exam_enabled': False,
+ 'entrance_exam_minimum_score_pct': None,
+ 'entrance_exam_id': None,
+ }
+ CourseMetadata.update_from_dict(metadata, course, request.user)
+
+ return HttpResponse(status=204)
+
+
+def _serialize_entrance_exam(entrance_exam_module):
+ """
+ Internal helper to convert an entrance exam module/object into JSON
+ """
+ return json.dumps({
+ 'locator': unicode(entrance_exam_module.location)
+ })
diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py
index d93ac2c42e..8610559f1f 100644
--- a/cms/djangoapps/contentstore/views/item.py
+++ b/cms/djangoapps/contentstore/views/item.py
@@ -13,6 +13,7 @@ from functools import partial
from static_replace import replace_static_urls
from xmodule_modifiers import wrap_xblock, request_token
+from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseBadRequest, HttpResponse, Http404
@@ -87,6 +88,17 @@ def usage_key_with_run(usage_key_string):
return usage_key
+def _filter_entrance_exam_grader(graders):
+ """
+ If the entrance exams feature is enabled we need to hide away the grader from
+ views/controls like the 'Grade as' dropdown that allows a course author to select
+ the grader type for a given section of a course
+ """
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ graders = [grader for grader in graders if grader.get('type') != u'Entrance Exam']
+ return graders
+
+
# pylint: disable=unused-argument
@require_http_methods(("DELETE", "GET", "PUT", "POST", "PATCH"))
@login_required
@@ -511,6 +523,15 @@ def _save_xblock(user, xblock, data=None, children_strings=None, metadata=None,
return JsonResponse(result, encoder=EdxJSONEncoder)
+@login_required
+@expect_json
+def create_item(request):
+ """
+ Exposes internal helper method without breaking existing bindings/dependencies
+ """
+ return _create_item(request)
+
+
@login_required
@expect_json
def _create_item(request):
@@ -549,6 +570,15 @@ def _create_item(request):
if display_name is not None:
metadata['display_name'] = display_name
+ # Entrance Exams: Chapter module positioning
+ child_position = None
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ is_entrance_exam = request.json.get('is_entrance_exam', False)
+ if category == 'chapter' and is_entrance_exam:
+ metadata['is_entrance_exam'] = is_entrance_exam
+ metadata['in_entrance_exam'] = True # Inherited metadata, all children will have it
+ child_position = 0
+
# TODO need to fix components that are sending definition_data as strings, instead of as dicts
# For now, migrate them into dicts here.
if isinstance(data, basestring):
@@ -562,8 +592,32 @@ def _create_item(request):
definition_data=data,
metadata=metadata,
runtime=parent.runtime,
+ position=child_position
)
+ # Entrance Exams: Grader assignment
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ course = store.get_course(usage_key.course_key)
+ if hasattr(course, 'entrance_exam_enabled') and course.entrance_exam_enabled:
+ if category == 'sequential' and request.json.get('parent_locator') == course.entrance_exam_id:
+ grader = {
+ "type": "Entrance Exam",
+ "min_count": 0,
+ "drop_count": 0,
+ "short_label": "Entrance",
+ "weight": 0
+ }
+ grading_model = CourseGradingModel.update_grader_from_json(
+ course.id,
+ grader,
+ request.user
+ )
+ CourseGradingModel.update_section_grader_type(
+ created_block,
+ grading_model['type'],
+ request.user
+ )
+
# VS[compat] cdodge: This is a hack because static_tabs also have references from the course module, so
# if we add one then we need to also add it to the policy information (i.e. metadata)
# we should remove this once we can break this reference from the course to static tabs
@@ -643,6 +697,15 @@ def _duplicate_item(parent_usage_key, duplicate_source_usage_key, user, display_
return dest_module.location
+@login_required
+@expect_json
+def delete_item(request, usage_key):
+ """
+ Exposes internal helper method without breaking existing bindings/dependencies
+ """
+ _delete_item(usage_key, request.user)
+
+
def _delete_item(usage_key, user):
"""
Deletes an existing xblock with the given usage_key.
@@ -781,6 +844,9 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
else:
graders = []
+ # Filter the graders data as needed
+ graders = _filter_entrance_exam_grader(graders)
+
# Compute the child info first so it can be included in aggregate information for the parent
should_visit_children = include_child_info and (course_outline and not is_xblock_unit or not course_outline)
if should_visit_children and xblock.has_children:
@@ -799,6 +865,11 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
visibility_state = None
published = modulestore().has_published_version(xblock) if not is_library_block else None
+ #instead of adding a new feature directly into xblock-info, we should add them into override_type.
+ override_type = {}
+ if getattr(xblock, "is_entrance_exam", None):
+ override_type['is_entrance_exam'] = xblock.is_entrance_exam
+
xblock_info = {
"id": unicode(xblock.location),
"display_name": xblock.display_name_with_default,
@@ -818,6 +889,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
"format": xblock.format,
"course_graders": json.dumps([grader.get('type') for grader in graders]),
"has_changes": has_changes,
+ "override_type": override_type,
}
if data is not None:
xblock_info["data"] = data
diff --git a/cms/djangoapps/contentstore/views/tests/test_entrance_exam.py b/cms/djangoapps/contentstore/views/tests/test_entrance_exam.py
new file mode 100644
index 0000000000..a2cf5c7043
--- /dev/null
+++ b/cms/djangoapps/contentstore/views/tests/test_entrance_exam.py
@@ -0,0 +1,252 @@
+"""
+Test module for Entrance Exams AJAX callback handler workflows
+"""
+import json
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.test.client import RequestFactory
+
+from contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase
+from contentstore.utils import reverse_url
+from contentstore.views.entrance_exam import create_entrance_exam
+from models.settings.course_grading import CourseGradingModel
+from models.settings.course_metadata import CourseMetadata
+from opaque_keys.edx.keys import UsageKey
+from student.tests.factories import UserFactory
+from xmodule.modulestore.django import modulestore
+
+if settings.FEATURES.get('MILESTONES_APP', False):
+ from milestones import api as milestones_api
+ from milestones.models import MilestoneRelationshipType
+ from util.milestones_helpers import serialize_user
+
+
+class EntranceExamHandlerTests(CourseTestCase):
+ """
+ Base test class for create, save, and delete
+ """
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ def setUp(self):
+ """
+ Shared scaffolding for individual test runs
+ """
+ super(EntranceExamHandlerTests, self).setUp()
+ self.course_key = self.course.id
+ self.usage_key = self.course.location
+ self.course_url = '/course/{}'.format(unicode(self.course.id))
+ self.exam_url = '/course/{}/entrance_exam/'.format(unicode(self.course.id))
+ MilestoneRelationshipType.objects.create(name='requires', active=True)
+ MilestoneRelationshipType.objects.create(name='fulfills', active=True)
+ self.milestone_relationship_types = milestones_api.get_milestone_relationship_types()
+
+ def test_contentstore_views_entrance_exam_post(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_post
+ """
+ resp = self.client.post(self.exam_url, {}, http_accept='application/json')
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+
+ # Reload the test course now that the exam module has been added
+ self.course = modulestore().get_course(self.course.id)
+ metadata = CourseMetadata.fetch_all(self.course)
+ self.assertTrue(metadata['entrance_exam_enabled'])
+ self.assertIsNotNone(metadata['entrance_exam_minimum_score_pct'])
+ self.assertIsNotNone(metadata['entrance_exam_id']['value'])
+ self.assertTrue(len(milestones_api.get_course_milestones(unicode(self.course.id))))
+ content_milestones = milestones_api.get_course_content_milestones(
+ unicode(self.course.id),
+ metadata['entrance_exam_id']['value'],
+ self.milestone_relationship_types['FULFILLS']
+ )
+ self.assertTrue(len(content_milestones))
+
+ def test_contentstore_views_entrance_exam_post_new_sequential_confirm_grader(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_post
+ """
+ resp = self.client.post(self.exam_url, {}, http_accept='application/json')
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+
+ # Reload the test course now that the exam module has been added
+ self.course = modulestore().get_course(self.course.id)
+
+ # Add a new child sequential to the exam module
+ # Confirm that the grader type is 'Entrance Exam'
+ chapter_locator_string = json.loads(resp.content).get('locator')
+ # chapter_locator = UsageKey.from_string(chapter_locator_string)
+ seq_data = {
+ 'category': "sequential",
+ 'display_name': "Entrance Exam Subsection",
+ 'parent_locator': chapter_locator_string,
+ }
+ resp = self.client.ajax_post(reverse_url('xblock_handler'), seq_data)
+ seq_locator_string = json.loads(resp.content).get('locator')
+ seq_locator = UsageKey.from_string(seq_locator_string)
+ section_grader_type = CourseGradingModel.get_section_grader_type(seq_locator)
+ self.assertEqual('Entrance Exam', section_grader_type['graderType'])
+
+ def test_contentstore_views_entrance_exam_get(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_get
+ """
+ resp = self.client.post(
+ self.exam_url,
+ {'entrance_exam_minimum_score_pct': settings.ENTRANCE_EXAM_MIN_SCORE_PCT},
+ http_accept='application/json'
+ )
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+
+ def test_contentstore_views_entrance_exam_delete(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_delete
+ """
+ resp = self.client.post(self.exam_url, {}, http_accept='application/json')
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+ resp = self.client.delete(self.exam_url)
+ self.assertEqual(resp.status_code, 204)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 404)
+
+ user = User.objects.create(
+ username='test_user',
+ email='test_user@edx.org',
+ is_active=True,
+ )
+ user.set_password('test')
+ user.save()
+ milestones = milestones_api.get_course_milestones(unicode(self.course_key))
+ self.assertEqual(len(milestones), 1)
+ milestone_key = '{}.{}'.format(milestones[0]['namespace'], milestones[0]['name'])
+ paths = milestones_api.get_course_milestones_fulfillment_paths(
+ unicode(self.course_key),
+ serialize_user(user)
+ )
+
+ # What we have now is a course milestone requirement and no valid fulfillment
+ # paths for the specified user. The LMS is going to have to ignore this situation,
+ # because we can't confidently prevent it from occuring at some point in the future.
+ # milestone_key_1 =
+ self.assertEqual(len(paths[milestone_key]), 0)
+
+ # Re-adding an entrance exam to the course should fix the missing link
+ # It wipes out any old entrance exam artifacts and inserts a new exam course chapter/module
+ resp = self.client.post(self.exam_url, {}, http_accept='application/json')
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+
+ def test_contentstore_views_entrance_exam_delete_bogus_course(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_delete_bogus_course
+ """
+ resp = self.client.delete('/course/bad/course/key/entrance_exam')
+ self.assertEqual(resp.status_code, 400)
+
+ def test_contentstore_views_entrance_exam_get_bogus_course(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_get_bogus_course
+ """
+ resp = self.client.get('/course/bad/course/key/entrance_exam')
+ self.assertEqual(resp.status_code, 400)
+
+ def test_contentstore_views_entrance_exam_get_bogus_exam(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_get_bogus_exam
+ """
+ resp = self.client.post(
+ self.exam_url,
+ {'entrance_exam_minimum_score_pct': '50'},
+ http_accept='application/json'
+ )
+ self.assertEqual(resp.status_code, 201)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 200)
+ self.course = modulestore().get_course(self.course.id)
+
+ # Should raise an ItemNotFoundError and return a 404
+ updated_metadata = {'entrance_exam_id': 'i4x://org.4/course_4/chapter/ed7c4c6a4d68409998e2c8554c4629d1'}
+ CourseMetadata.update_from_dict(
+ updated_metadata,
+ self.course,
+ self.user,
+ )
+ self.course = modulestore().get_course(self.course.id)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 404)
+
+ # Should raise an InvalidKeyError and return a 404
+ updated_metadata = {'entrance_exam_id': '123afsdfsad90f87'}
+ CourseMetadata.update_from_dict(
+ updated_metadata,
+ self.course,
+ self.user,
+ )
+ self.course = modulestore().get_course(self.course.id)
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 404)
+
+ def test_contentstore_views_entrance_exam_post_bogus_course(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_post_bogus_course
+ """
+ resp = self.client.post(
+ '/course/bad/course/key/entrance_exam',
+ {},
+ http_accept='application/json'
+ )
+ self.assertEqual(resp.status_code, 400)
+
+ def test_contentstore_views_entrance_exam_post_invalid_http_accept(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_post_invalid_http_accept
+ """
+ resp = self.client.post(
+ '/course/bad/course/key/entrance_exam',
+ {},
+ http_accept='text/html'
+ )
+ self.assertEqual(resp.status_code, 400)
+
+ def test_contentstore_views_entrance_exam_get_invalid_user(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_get_invalid_user
+ """
+ user = User.objects.create(
+ username='test_user',
+ email='test_user@edx.org',
+ is_active=True,
+ )
+ user.set_password('test')
+ user.save()
+ self.client = AjaxEnabledTestClient()
+ self.client.login(username='test_user', password='test')
+ resp = self.client.get(self.exam_url)
+ self.assertEqual(resp.status_code, 403)
+
+ def test_contentstore_views_entrance_exam_unsupported_method(self):
+ """
+ Unit Test: test_contentstore_views_entrance_exam_unsupported_method
+ """
+ resp = self.client.put(self.exam_url)
+ self.assertEqual(resp.status_code, 405)
+
+ def test_entrance_exam_view_direct_missing_score_setting(self):
+ """
+ Unit Test: test_entrance_exam_view_direct_missing_score_setting
+ """
+ user = UserFactory()
+ user.is_staff = True
+ request = RequestFactory()
+ request.user = user
+
+ resp = create_entrance_exam(request, self.course.id, None)
+ self.assertEqual(resp.status_code, 201)
diff --git a/cms/djangoapps/models/settings/course_details.py b/cms/djangoapps/models/settings/course_details.py
index 509c2df6a2..afb215e018 100644
--- a/cms/djangoapps/models/settings/course_details.py
+++ b/cms/djangoapps/models/settings/course_details.py
@@ -4,6 +4,8 @@ import datetime
import json
from json.encoder import JSONEncoder
+from django.conf import settings
+
from opaque_keys.edx.locations import Location
from xmodule.modulestore.exceptions import ItemNotFoundError
from contentstore.utils import course_image_url
@@ -19,6 +21,9 @@ ABOUT_ATTRIBUTES = [
'short_description',
'overview',
'effort',
+ 'entrance_exam_enabled',
+ 'entrance_exam_id',
+ 'entrance_exam_minimum_score_pct',
]
@@ -40,6 +45,12 @@ class CourseDetails(object):
self.course_image_name = ""
self.course_image_asset_path = "" # URL of the course image
self.pre_requisite_courses = [] # pre-requisite courses
+ self.entrance_exam_enabled = "" # is entrance exam enabled
+ self.entrance_exam_id = "" # the content location for the entrance exam
+ self.entrance_exam_minimum_score_pct = settings.FEATURES.get(
+ 'ENTRANCE_EXAM_MIN_SCORE_PCT',
+ '50'
+ ) # minimum passing score for entrance exam content module/tree
@classmethod
def _fetch_about_attribute(cls, course_key, attribute):
@@ -168,7 +179,8 @@ class CourseDetails(object):
# NOTE: below auto writes to the db w/o verifying that any of the fields actually changed
# to make faster, could compare against db or could have client send over a list of which fields changed.
for attribute in ABOUT_ATTRIBUTES:
- cls.update_about_item(course_key, attribute, jsondict[attribute], descriptor, user)
+ if attribute in jsondict:
+ cls.update_about_item(course_key, attribute, jsondict[attribute], descriptor, user)
recomposed_video_tag = CourseDetails.recompose_video_tag(jsondict['intro_video'])
cls.update_about_item(course_key, 'video', recomposed_video_tag, descriptor, user)
diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py
index f7b63570af..5a7b979154 100644
--- a/cms/djangoapps/models/settings/course_metadata.py
+++ b/cms/djangoapps/models/settings/course_metadata.py
@@ -1,3 +1,6 @@
+"""
+Django module for Course Metadata class -- manages advanced settings and related parameters
+"""
from xblock.fields import Scope
from xmodule.modulestore.django import modulestore
from django.utils.translation import ugettext as _
@@ -33,7 +36,10 @@ class CourseMetadata(object):
'tags', # from xblock
'visible_to_staff_only',
'group_access',
- 'pre_requisite_courses'
+ 'pre_requisite_courses',
+ 'entrance_exam_enabled',
+ 'entrance_exam_minimum_score_pct',
+ 'entrance_exam_id',
]
@classmethod
@@ -61,21 +67,28 @@ class CourseMetadata(object):
persistence and return a CourseMetadata model.
"""
result = {}
+ metadata = cls.fetch_all(descriptor)
+ for key, value in metadata.iteritems():
+ if key in cls.filtered_list():
+ continue
+ result[key] = value
+ return result
+ @classmethod
+ def fetch_all(cls, descriptor):
+ """
+ Fetches all key:value pairs from persistence and returns a CourseMetadata model.
+ """
+ result = {}
for field in descriptor.fields.values():
if field.scope != Scope.settings:
continue
-
- if field.name in cls.filtered_list():
- continue
-
result[field.name] = {
'value': field.read_json(descriptor),
'display_name': _(field.display_name),
'help': _(field.help),
'deprecated': field.runtime_options.get('deprecated', False)
}
-
return result
@classmethod
diff --git a/cms/envs/bok_choy.env.json b/cms/envs/bok_choy.env.json
index 685d2f7b63..c24495433d 100644
--- a/cms/envs/bok_choy.env.json
+++ b/cms/envs/bok_choy.env.json
@@ -68,6 +68,8 @@
"ENABLE_DISCUSSION_SERVICE": true,
"ENABLE_INSTRUCTOR_ANALYTICS": true,
"ENABLE_S3_GRADE_DOWNLOADS": true,
+ "ENTRANCE_EXAMS": true,
+ "MILESTONES_APP": true,
"PREVIEW_LMS_BASE": "localhost:8003",
"SUBDOMAIN_BRANDING": false,
"SUBDOMAIN_COURSE_LISTINGS": false,
diff --git a/cms/envs/bok_choy.py b/cms/envs/bok_choy.py
index 6b6470e78b..37bb2e2185 100644
--- a/cms/envs/bok_choy.py
+++ b/cms/envs/bok_choy.py
@@ -60,6 +60,9 @@ FEATURES['MILESTONES_APP'] = True
# Enable pre-requisite course
FEATURES['ENABLE_PREREQUISITE_COURSES'] = True
+########################### Entrance Exams #################################
+FEATURES['ENTRANCE_EXAMS'] = True
+
# Unfortunately, we need to use debug mode to serve staticfiles
DEBUG = True
diff --git a/cms/envs/common.py b/cms/envs/common.py
index 2f5a676e41..f0818b2db3 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -113,6 +113,7 @@ FEATURES = {
# Turn off Video Upload Pipeline through Studio, by default
'ENABLE_VIDEO_UPLOAD_PIPELINE': False,
+
# Is this an edX-owned domain? (edx.org)
# for consistency in user-experience, keep the value of this feature flag
# in sync with the one in lms/envs/common.py
@@ -134,7 +135,14 @@ FEATURES = {
# Prerequisite courses feature flag
'ENABLE_PREREQUISITE_COURSES': False,
+
+ # Toggle course milestones app/feature
+ 'MILESTONES_APP': False,
+
+ # Toggle course entrance exams feature
+ 'ENTRANCE_EXAMS': False,
}
+
ENABLE_JASMINE = False
@@ -751,7 +759,9 @@ OPTIONAL_APPS = (
# edxval
'edxval',
- 'milestones'
+
+ # milestones
+ 'milestones',
)
@@ -786,6 +796,9 @@ MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB = 10
# a file that exceeds the above size
MAX_ASSET_UPLOAD_FILE_SIZE_URL = ""
+### Default value for entrance exam minimum score
+ENTRANCE_EXAM_MIN_SCORE_PCT = 50
+
################ ADVANCED_COMPONENT_TYPES ###############
ADVANCED_COMPONENT_TYPES = [
diff --git a/cms/envs/devstack.py b/cms/envs/devstack.py
index 50fc0a1b37..f714172955 100644
--- a/cms/envs/devstack.py
+++ b/cms/envs/devstack.py
@@ -75,6 +75,15 @@ DEBUG_TOOLBAR_CONFIG = {
# Stacktraces slow down page loads drastically (for pages with lots of queries).
DEBUG_TOOLBAR_MONGO_STACKTRACES = False
+
+################################ MILESTONES ################################
+FEATURES['MILESTONES_APP'] = True
+
+
+################################ ENTRANCE EXAMS ################################
+FEATURES['ENTRANCE_EXAMS'] = True
+
+
###############################################################################
# See if the developer has any local overrides.
try:
diff --git a/cms/envs/test.py b/cms/envs/test.py
index e3a3294360..63cc896d9d 100644
--- a/cms/envs/test.py
+++ b/cms/envs/test.py
@@ -232,7 +232,15 @@ FEATURES['USE_MICROSITES'] = True
# the one in lms/envs/test.py
FEATURES['ENABLE_DISCUSSION_SERVICE'] = False
+
# Enable content libraries code for the tests
FEATURES['ENABLE_CONTENT_LIBRARIES'] = True
FEATURES['ENABLE_EDXNOTES'] = True
+
+# MILESTONES
+FEATURES['MILESTONES_APP'] = True
+
+# ENTRANCE EXAMS
+FEATURES['ENTRANCE_EXAMS'] = True
+ENTRANCE_EXAM_MIN_SCORE_PCT = 50
diff --git a/cms/static/images/spinner-on-grey.gif b/cms/static/images/spinner-on-grey.gif
new file mode 100644
index 0000000000..f43d52e4f4
Binary files /dev/null and b/cms/static/images/spinner-on-grey.gif differ
diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js
index 58b58fb7af..0b2124975a 100644
--- a/cms/static/js/models/settings/course_details.js
+++ b/cms/static/js/models/settings/course_details.js
@@ -1,4 +1,5 @@
-define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) {
+define(["backbone", "underscore", "gettext", "js/models/validation_helpers"],
+ function(Backbone, _, gettext, ValidationHelpers) {
var CourseDetails = Backbone.Model.extend({
defaults: {
@@ -16,7 +17,9 @@ var CourseDetails = Backbone.Model.extend({
effort: null, // an int or null,
course_image_name: '', // the filename
course_image_asset_path: '', // the full URL (/c4x/org/course/num/asset/filename)
- pre_requisite_courses: []
+ pre_requisite_courses: [],
+ entrance_exam_enabled : '',
+ entrance_exam_minimum_score_pct: '50'
},
validate: function(newattrs) {
@@ -44,6 +47,16 @@ var CourseDetails = Backbone.Model.extend({
}
// TODO check if key points to a real video using google's youtube api
}
+ if(_.has(newattrs, 'entrance_exam_minimum_score_pct')){
+ var range = {
+ min: 1,
+ max: 100
+ };
+ if(!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)){
+ errors.entrance_exam_minimum_score_pct = gettext("Please enter an integer between "
+ + range.min +" and "+ range.max +".");
+ }
+ }
if (!_.isEmpty(errors)) return errors;
// NOTE don't return empty errors as that will be interpreted as an error state
},
diff --git a/cms/static/js/models/validation_helpers.js b/cms/static/js/models/validation_helpers.js
new file mode 100644
index 0000000000..5a008fc798
--- /dev/null
+++ b/cms/static/js/models/validation_helpers.js
@@ -0,0 +1,20 @@
+/**
+ * Provide helper methods for modal validation.
+*/
+define(["jquery"],
+ function($) {
+
+ var validateIntegerRange = function(attributeVal, range) {
+ //Validating attribute should have an integer value and should be under the given range.
+ var isIntegerUnderRange = true;
+ var value = Math.round(attributeVal); // see if this ensures value saved is int
+ if (!isFinite(value) || /\D+/.test(attributeVal) || value < range.min || value > range.max) {
+ isIntegerUnderRange = false;
+ }
+ return isIntegerUnderRange;
+ }
+
+ return {
+ 'validateIntegerRange': validateIntegerRange
+ }
+ });
diff --git a/cms/static/js/models/xblock_info.js b/cms/static/js/models/xblock_info.js
index 4e643f7d5f..34d82ebc1f 100644
--- a/cms/static/js/models/xblock_info.js
+++ b/cms/static/js/models/xblock_info.js
@@ -131,7 +131,11 @@ function(Backbone, _, str, ModuleUtils) {
* content groups. Note that this is not a recursive property. Will only be present if
* publishing info was explicitly requested.
*/
- 'has_content_group_components': null
+ 'has_content_group_components': null,
+ /**
+ * Indicate the type of xblock
+ */
+ 'override_type': null
},
initialize: function () {
@@ -168,6 +172,19 @@ function(Backbone, _, str, ModuleUtils) {
return !this.get('published') || this.get('has_changes');
},
+ canBeDeleted: function(){
+ //get the type of xblock
+ if(this.get('override_type') != null) {
+ var type = this.get('override_type');
+
+ //hide/remove the delete trash icon if type is entrance exam.
+ if (_.has(type, 'is_entrance_exam') && type['is_entrance_exam']) {
+ return false;
+ }
+ }
+ return true;
+ },
+
/**
* Return a list of convenience methods to check affiliation to the category.
* @return {Array}
diff --git a/cms/static/js/spec/views/settings/main_spec.js b/cms/static/js/spec/views/settings/main_spec.js
index 7fea35e848..81c10613fe 100644
--- a/cms/static/js/spec/views/settings/main_spec.js
+++ b/cms/static/js/spec/views/settings/main_spec.js
@@ -20,7 +20,9 @@ define([
effort : null,
course_image_name : '',
course_image_asset_path : '',
- pre_requisite_courses : []
+ pre_requisite_courses : [],
+ entrance_exam_enabled : '',
+ entrance_exam_minimum_score_pct: '50'
},
mockSettingsPage = readFixtures('mock/mock-settings-page.underscore');
@@ -76,5 +78,45 @@ define([
);
AjaxHelpers.respondWithJson(requests, expectedJson);
});
+
+ it('should save entrance exam course details information correctly', function () {
+ var entrance_exam_minimum_score_pct = '60';
+ var entrance_exam_enabled = 'true';
+
+ var entrance_exam_min_score = this.view.$('#entrance-exam-minimum-score-pct');
+ var entrance_exam_enabled_field = this.view.$('#entrance-exam-enabled');
+
+ var requests = AjaxHelpers.requests(this),
+ expectedJson = $.extend(true, {}, modelData, {
+ entrance_exam_enabled: entrance_exam_enabled,
+ entrance_exam_minimum_score_pct: entrance_exam_minimum_score_pct
+ });
+
+ expect(this.view.$('.div-grade-requirements div')).toBeHidden();
+
+ // select the entrance-exam-enabled checkbox. grade requirement section should be visible
+ entrance_exam_enabled_field
+ .attr('checked', entrance_exam_enabled)
+ .trigger('change');
+ expect(this.view.$('.div-grade-requirements div')).toBeVisible();
+
+ //input some invalid values.
+ expect(entrance_exam_min_score.val('101').trigger('input')).toHaveClass("error");
+ expect(entrance_exam_min_score.val('invalidVal').trigger('input')).toHaveClass("error");
+
+ //if input an empty value, model should be populated with the default value.
+ entrance_exam_min_score.val('').trigger('input');
+ expect(this.model.get('entrance_exam_minimum_score_pct'))
+ .toEqual(this.model.defaults.entrance_exam_minimum_score_pct);
+
+ // input a valid value for entrance exam minimum score.
+ entrance_exam_min_score.val(entrance_exam_minimum_score_pct).trigger('input');
+
+ this.view.saveView();
+ AjaxHelpers.expectJsonRequest(
+ requests, 'POST', urlRoot, expectedJson
+ );
+ AjaxHelpers.respondWithJson(requests, expectedJson);
+ });
});
});
diff --git a/cms/static/js/views/settings/main.js b/cms/static/js/views/settings/main.js
index 8e10e49221..d6978987fe 100644
--- a/cms/static/js/views/settings/main.js
+++ b/cms/static/js/views/settings/main.js
@@ -64,10 +64,21 @@ var DetailsView = ValidatingView.extend({
var imageURL = this.model.get('course_image_asset_path');
this.$el.find('#course-image-url').val(imageURL);
this.$el.find('#course-image').attr('src', imageURL);
+
var pre_requisite_courses = this.model.get('pre_requisite_courses');
pre_requisite_courses = pre_requisite_courses.length > 0 ? pre_requisite_courses : '';
this.$el.find('#' + this.fieldToSelectorMap['pre_requisite_courses']).val(pre_requisite_courses);
+ if (this.model.get('entrance_exam_enabled') == 'true') {
+ this.$('#' + this.fieldToSelectorMap['entrance_exam_enabled']).attr('checked', this.model.get('entrance_exam_enabled'));
+ this.$('.div-grade-requirements').show();
+ }
+ else {
+ this.$('#' + this.fieldToSelectorMap['entrance_exam_enabled']).removeAttr('checked');
+ this.$('.div-grade-requirements').hide();
+ }
+ this.$('#' + this.fieldToSelectorMap['entrance_exam_minimum_score_pct']).val(this.model.get('entrance_exam_minimum_score_pct'));
+
return this;
},
fieldToSelectorMap : {
@@ -80,7 +91,9 @@ var DetailsView = ValidatingView.extend({
'intro_video' : 'course-introduction-video',
'effort' : "course-effort",
'course_image_asset_path': 'course-image-url',
- 'pre_requisite_courses': 'pre-requisite-course'
+ 'pre_requisite_courses': 'pre-requisite-course',
+ 'entrance_exam_enabled': 'entrance-exam-enabled',
+ 'entrance_exam_minimum_score_pct': 'entrance-exam-minimum-score-pct'
},
updateTime : function(e) {
@@ -156,6 +169,23 @@ var DetailsView = ValidatingView.extend({
case 'course-effort':
this.setField(event);
break;
+ case 'entrance-exam-enabled':
+ if($(event.currentTarget).is(":checked")){
+ this.$('.div-grade-requirements').show();
+ }else{
+ this.$('.div-grade-requirements').hide();
+ }
+ this.setField(event);
+ break;
+ case 'entrance-exam-minimum-score-pct':
+ // If the val is an empty string then update model with default value.
+ if ($(event.currentTarget).val() === '') {
+ this.model.set('entrance_exam_minimum_score_pct', this.model.defaults.entrance_exam_minimum_score_pct);
+ }
+ else {
+ this.setField(event);
+ }
+ break;
case 'course-short-description':
this.setField(event);
break;
diff --git a/cms/static/js/views/validation.js b/cms/static/js/views/validation.js
index bbca2e67a0..435274b9ce 100644
--- a/cms/static/js/views/validation.js
+++ b/cms/static/js/views/validation.js
@@ -60,7 +60,12 @@ var ValidatingView = BaseView.extend({
// Set model field and return the new value.
this.clearValidationErrors();
var field = this.selectorToField[event.currentTarget.id];
- var newVal = $(event.currentTarget).val();
+ var newVal = ''
+ if(event.currentTarget.type == 'checkbox'){
+ newVal = $(event.currentTarget).is(":checked").toString();
+ }else{
+ newVal = $(event.currentTarget).val();
+ }
this.model.set(field, newVal);
this.model.isValid();
return newVal;
diff --git a/cms/static/sass/views/_settings.scss b/cms/static/sass/views/_settings.scss
index 4ce762a91c..273db8d2e1 100644
--- a/cms/static/sass/views/_settings.scss
+++ b/cms/static/sass/views/_settings.scss
@@ -100,8 +100,12 @@
@include transition(color $tmg-f2 ease-in-out 0s);
display: block;
margin-top: ($baseline/4);
- color: $gray-l3;
+ color: $gray-d1;
}
+ .tip-inline{
+ display: inline;
+ margin-left: 5px;
+ }
.message-error {
@extend %t-copy-sub1;
@@ -126,6 +130,30 @@
.list-input {
@extend %cont-no-list;
+ .show-data{
+ .heading{
+ border: 1px solid #E0E0E0;
+ padding: 5px 15px;
+ margin-top: 5px;
+ }
+ .div-grade-requirements{
+ border: 1px solid #E0E0E0;
+ border-top: none;
+ padding: 10px 15px;
+ label{font-weight: 600;}
+ input#entrance-exam-minimum-score-pct{
+ height: 40px;
+ font-size: 18px;
+ }
+ }
+ }
+ #heading-entrance-exam{
+ font-weight: 600;
+ }
+
+ label[for="entrance-exam-enabled"] {
+ font-size: 14px;
+ }
.field {
margin: 0 0 ($baseline*2) 0;
diff --git a/cms/templates/js/course-outline.underscore b/cms/templates/js/course-outline.underscore
index 6bb9311a9b..711b21e6ba 100644
--- a/cms/templates/js/course-outline.underscore
+++ b/cms/templates/js/course-outline.underscore
@@ -78,12 +78,14 @@ if (xblockInfo.get('graded')) {
<% } %>
-
-
-
- <%= gettext('Delete') %>
-
-
+ <% if (xblockInfo.canBeDeleted()) { %>
+
+
+
+ <%= gettext('Delete') %>
+
+
+ <% } %>
diff --git a/cms/templates/js/mock/mock-settings-page.underscore b/cms/templates/js/mock/mock-settings-page.underscore
index be45253da1..1dd28b53b9 100644
--- a/cms/templates/js/mock/mock-settings-page.underscore
+++ b/cms/templates/js/mock/mock-settings-page.underscore
@@ -74,6 +74,19 @@
Course that students must complete before beginning this course
set pre-requisite course
+ ${_("Entrance Exam")}
+
+
+
+ ${_("Require students to pass an exam before beginning the course.")}
+
+
+
${_("To create your course entrance exam, go to the ")}${_("Course Outline")} ${_(". An Entrance Exam section will be created automatically.")}
+
${_("Minimum Passing Score")}
+
${_(" %")}
+
${_("The minimum score a student must receive to pass the entrance exam.")}
+
+
diff --git a/cms/templates/settings.html b/cms/templates/settings.html
index 280a71b7bd..06cdd5d7e8 100644
--- a/cms/templates/settings.html
+++ b/cms/templates/settings.html
@@ -322,6 +322,23 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
% endif
+ % if settings.FEATURES.get('ENTRANCE_EXAMS'):
+
+ ${_("Entrance Exam")}
+
+
+
+ ${_("Require students to pass an exam before beginning the course.")}
+
+
+
${_("You can now view and author your course entrance exam from the ")}${_("Course Outline")}
+
${_("Grade Requirements")}
+
${_(" %")}
+
${_("The score student must meet in order to successfully complete the entrance exam. ")}
+
+
+
+ % endif
% endif
diff --git a/cms/urls.py b/cms/urls.py
index ff5d95f991..4a216e1883 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -158,6 +158,12 @@ if settings.FEATURES.get('AUTOMATIC_AUTH_FOR_TESTING'):
url(r'^auto_auth$', 'student.views.auto_auth'),
)
+# enable entrance exams
+if settings.FEATURES.get('ENTRANCE_EXAMS'):
+ urlpatterns += (
+ url(r'^course/{}/entrance_exam/?$'.format(settings.COURSE_KEY_PATTERN), 'contentstore.views.entrance_exam'),
+ )
+
if settings.DEBUG:
try:
from .urls_dev import urlpatterns as dev_urlpatterns
diff --git a/common/djangoapps/util/milestones_helpers.py b/common/djangoapps/util/milestones_helpers.py
index 8668c472ce..9b8048a18a 100644
--- a/common/djangoapps/util/milestones_helpers.py
+++ b/common/djangoapps/util/milestones_helpers.py
@@ -1,6 +1,6 @@
# pylint: disable=invalid-name
"""
-Helper methods for milestones api calls.
+Utility library for working with the edx-milestones app
"""
from django.conf import settings
@@ -20,6 +20,10 @@ from milestones.api import (
)
from milestones.models import MilestoneRelationshipType
+NAMESPACE_CHOICES = {
+ 'ENTRANCE_EXAM': 'entrance_exams'
+}
+
def add_prerequisite_course(course_key, prerequisite_course_key):
"""
@@ -165,3 +169,21 @@ def seed_milestone_relationship_types():
if settings.FEATURES.get('MILESTONES_APP', False):
MilestoneRelationshipType.objects.create(name='requires')
MilestoneRelationshipType.objects.create(name='fulfills')
+
+
+def generate_milestone_namespace(namespace, course_key=None):
+ """
+ Returns a specifically-formatted namespace string for the specified type
+ """
+ if namespace in NAMESPACE_CHOICES.values():
+ if namespace == 'entrance_exams':
+ return '{}.{}'.format(unicode(course_key), NAMESPACE_CHOICES['ENTRANCE_EXAM'])
+
+
+def serialize_user(user):
+ """
+ Returns a milestones-friendly representation of a user object
+ """
+ return {
+ 'id': user.id,
+ }
diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py
index cb445883e1..2633f514e3 100644
--- a/common/lib/xmodule/xmodule/course_module.py
+++ b/common/lib/xmodule/xmodule/course_module.py
@@ -1,3 +1,6 @@
+"""
+Django module container for classes and operations related to the "Course Module" content type
+"""
import logging
from cStringIO import StringIO
from math import exp
@@ -8,12 +11,13 @@ from datetime import datetime
import dateutil.parser
from lazy import lazy
+
from xmodule.seq_module import SequenceDescriptor, SequenceModule
from xmodule.graders import grader_from_conf
from xmodule.tabs import CourseTabList
import json
-from xblock.fields import Scope, List, String, Dict, Boolean, Integer
+from xblock.fields import Scope, List, String, Dict, Boolean, Integer, Float
from .fields import Date
from django.utils.timezone import UTC
@@ -657,6 +661,31 @@ class CourseFields(object):
{"display_name": _("None"), "value": CATALOG_VISIBILITY_NONE}]
)
+ entrance_exam_enabled = Boolean(
+ display_name=_("Entrance Exam Enabled"),
+ help=_(
+ "Specify whether students must complete an entrance exam before they can view your course content." +
+ "Note, you must enable Entrance Exams for this course setting to take effect."),
+ default=False,
+ scope=Scope.settings,
+ )
+
+ entrance_exam_minimum_score_pct = Float(
+ display_name=_("Entrance Exam Minimum Score (%)"),
+ help=_(
+ "Specify a minimum percentage score for an entrance exam before students can view your course content." +
+ "Note, you must enable Entrance Exams for this course setting to take effect."),
+ default=65,
+ scope=Scope.settings,
+ )
+
+ entrance_exam_id = String(
+ display_name=_("Entrance Exam ID"),
+ help=_("Content module identifier (location) of entrance exam."),
+ default=None,
+ scope=Scope.settings,
+ )
+
class CourseDescriptor(CourseFields, SequenceDescriptor):
module_class = SequenceModule
diff --git a/common/lib/xmodule/xmodule/modulestore/inheritance.py b/common/lib/xmodule/xmodule/modulestore/inheritance.py
index b8cd344510..022eb92b58 100644
--- a/common/lib/xmodule/xmodule/modulestore/inheritance.py
+++ b/common/lib/xmodule/xmodule/modulestore/inheritance.py
@@ -177,6 +177,14 @@ class InheritanceMixin(XBlockMixin):
scope=Scope.user_info
)
+ in_entrance_exam = Boolean(
+ display_name=_("Tag this module as part of an Entrance Exam section"),
+ help=_("Enter true or false. If true, answer submissions for problem modules will be "
+ "considered in the Entrance Exam scoring/gating algorithm."),
+ scope=Scope.settings,
+ default=False
+ )
+
def compute_inherited_metadata(descriptor):
"""Given a descriptor, traverse all of its descendants and do metadata
diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py
index 85564417b1..80e6d5cf80 100644
--- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py
+++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py
@@ -1225,7 +1225,13 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
# attach to parent if given
if 'detached' not in xblock._class_tags:
parent = self.get_item(parent_usage_key)
- parent.children.append(xblock.location)
+
+ # Originally added to support entrance exams (settings.FEATURES.get('ENTRANCE_EXAMS'))
+ if kwargs.get('position') is None:
+ parent.children.append(xblock.location)
+ else:
+ parent.children.insert(kwargs.get('position'), xblock.location)
+
self.update_item(parent, user_id)
return xblock
diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
index 9e9b09ebd2..093e90c038 100644
--- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
@@ -1510,7 +1510,16 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
raise ItemNotFoundError(parent_usage_key)
parent = new_structure['blocks'][block_id]
- parent['fields'].setdefault('children', []).append(BlockKey.from_usage_key(xblock.location))
+
+ # Originally added to support entrance exams (settings.FEATURES.get('ENTRANCE_EXAMS'))
+ if kwargs.get('position') is None:
+ parent['fields'].setdefault('children', []).append(BlockKey.from_usage_key(xblock.location))
+ else:
+ parent['fields'].setdefault('children', []).insert(
+ kwargs.get('position'),
+ BlockKey.from_usage_key(xblock.location)
+ )
+
if parent['edit_info']['update_version'] != new_structure['_id']:
# if the parent hadn't been previously changed in this bulk transaction, indicate that it's
# part of the bulk transaction
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
index 737e0c8b7a..38e6e30e2c 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
@@ -676,6 +676,35 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
finally:
shutil.rmtree(root_dir)
+ def test_draft_modulestore_create_child_with_position(self):
+ """
+ This test is designed to hit a specific set of use cases having to do with
+ the child positioning logic found in mongo/base.py:create_child()
+ """
+ # Set up the draft module store
+ course = self.draft_store.create_course("TestX", "ChildTest", "1234_A1", 1)
+ first_child = self.draft_store.create_child(
+ self.dummy_user,
+ course.location,
+ "chapter",
+ block_id=course.location.block_id
+ )
+ second_child = self.draft_store.create_child(
+ self.dummy_user,
+ course.location,
+ "chapter",
+ block_id=course.location.block_id,
+ position=0
+ )
+
+ # First child should have been moved to second position, and better child takes the lead
+ course = self.draft_store.get_course(course.id)
+ self.assertEqual(unicode(course.children[1]), unicode(first_child.location))
+ self.assertEqual(unicode(course.children[0]), unicode(second_child.location))
+
+ # Clean up the data so we don't break other tests which apparently expect a particular state
+ self.draft_store.delete_course(course.id, self.dummy_user)
+
class TestMongoModuleStoreWithNoAssetCollection(TestMongoModuleStore):
'''
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
index 27493d9180..6edf6c6d4e 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
@@ -1396,6 +1396,41 @@ class TestItemCrud(SplitModuleTest):
for _ in range(4):
self.create_subtree_for_deletion(node_loc, category_queue[1:])
+ def test_split_modulestore_create_child_with_position(self):
+ """
+ This test is designed to hit a specific set of use cases having to do with
+ the child positioning logic found in split_mongo/split.py:create_child()
+ """
+ # Set up the split module store
+ store = modulestore()
+ user = random.getrandbits(32)
+ course_key = CourseLocator('test_org', 'test_transaction', 'test_run')
+ with store.bulk_operations(course_key):
+ new_course = store.create_course('test_org', 'test_transaction', 'test_run', user, BRANCH_NAME_DRAFT)
+ new_course_locator = new_course.id
+ versionless_course_locator = new_course_locator.version_agnostic()
+ first_child = store.create_child(
+ self.user_id,
+ new_course.location,
+ "chapter"
+ )
+ refetch_course = store.get_course(versionless_course_locator)
+ second_child = store.create_child(
+ self.user_id,
+ refetch_course.location,
+ "chapter",
+ position=0
+ )
+
+ # First child should have been moved to second position, and better child takes the lead
+ refetch_course = store.get_course(versionless_course_locator)
+ children = refetch_course.get_children()
+ self.assertEqual(unicode(children[1].location), unicode(first_child.location))
+ self.assertEqual(unicode(children[0].location), unicode(second_child.location))
+
+ # Clean up the data so we don't break other tests which apparently expect a particular state
+ store.delete_course(refetch_course.id, user)
+
class TestCourseCreation(SplitModuleTest):
"""
diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py
index d07447aab0..2156f0d18f 100644
--- a/common/lib/xmodule/xmodule/seq_module.py
+++ b/common/lib/xmodule/xmodule/seq_module.py
@@ -4,7 +4,7 @@ import warnings
from lxml import etree
-from xblock.fields import Integer, Scope
+from xblock.fields import Integer, Scope, Boolean
from xblock.fragment import Fragment
from pkg_resources import resource_string
@@ -45,6 +45,16 @@ class SequenceFields(object):
scope=Scope.user_state,
)
+ # Entrance Exam flag -- see cms/contentstore/views/entrance_exam.py for usage
+ is_entrance_exam = Boolean(
+ display_name=_("Is Entrance Exam"),
+ help=_(
+ "Tag this course module as an Entrance Exam. " +
+ "Note, you must enable Entrance Exams for this course setting to take effect."
+ ),
+ scope=Scope.settings,
+ )
+
class SequenceModule(SequenceFields, XModule):
''' Layout module which lays out content in a temporal sequence
diff --git a/common/test/acceptance/pages/studio/settings.py b/common/test/acceptance/pages/studio/settings.py
index 96d5bd2301..432246f4ce 100644
--- a/common/test/acceptance/pages/studio/settings.py
+++ b/common/test/acceptance/pages/studio/settings.py
@@ -1,6 +1,7 @@
"""
Course Schedule and Details Settings page.
"""
+from bok_choy.promise import EmptyPromise
from .course_page import CoursePage
from .utils import press_the_notification_button
@@ -23,11 +24,42 @@ class SettingsPage(CoursePage):
"""
return self.q(css='#pre-requisite-course')
- def save_changes(self):
+ @property
+ def entrance_exam_field(self):
"""
- Clicks save button.
+ Returns the enable entrance exam checkbox.
+ """
+ return self.q(css='#entrance-exam-enabled').execute()
+
+ def require_entrance_exam(self, required=True):
+ """
+ Set the entrance exam requirement via the checkbox.
+ """
+ checkbox = self.entrance_exam_field[0]
+ selected = checkbox.is_selected()
+ if required and not selected:
+ checkbox.click()
+ self.wait_for_element_visibility(
+ '#entrance-exam-minimum-score-pct',
+ 'Entrance exam minimum score percent is visible'
+ )
+ if not required and selected:
+ checkbox.click()
+ self.wait_for_element_invisibility(
+ '#entrance-exam-minimum-score-pct',
+ 'Entrance exam minimum score percent is visible'
+ )
+
+ def save_changes(self, wait_for_confirmation=True):
+ """
+ Clicks save button, waits for confirmation unless otherwise specified
"""
press_the_notification_button(self, "save")
+ if wait_for_confirmation:
+ EmptyPromise(
+ lambda: self.q(css='#alert-confirmation-title').present,
+ 'Waiting for save confirmation...'
+ ).fulfill()
def refresh_page(self):
"""
diff --git a/common/test/acceptance/tests/helpers.py b/common/test/acceptance/tests/helpers.py
index b0851c4d3e..19da396f13 100644
--- a/common/test/acceptance/tests/helpers.py
+++ b/common/test/acceptance/tests/helpers.py
@@ -221,6 +221,19 @@ def is_option_value_selected(browser_query, value):
return ddl_selected_value == value
+def element_has_text(page, css_selector, text):
+ """
+ Return true if the given text is present in the list.
+ """
+ text_present = False
+ text_list = page.q(css=css_selector).text
+
+ if len(text_list) > 0 and (text in text_list):
+ text_present = True
+
+ return text_present
+
+
class UniqueCourseTest(WebAppTest):
"""
Test that provides a unique course ID.
diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py
index 307d973d64..55e62219b0 100644
--- a/common/test/acceptance/tests/lms/test_lms.py
+++ b/common/test/acceptance/tests/lms/test_lms.py
@@ -7,13 +7,14 @@ from textwrap import dedent
from unittest import skip
from nose.plugins.attrib import attr
-from bok_choy.web_app_test import WebAppTest
from bok_choy.promise import EmptyPromise
+from bok_choy.web_app_test import WebAppTest
from ..helpers import (
UniqueCourseTest,
load_data_str,
generate_course_key,
select_option_by_value,
+ element_has_text
)
from ...pages.lms.auto_auth import AutoAuthPage
from ...pages.common.logout import LogoutPage
@@ -27,6 +28,7 @@ from ...pages.lms.dashboard import DashboardPage
from ...pages.lms.problem import ProblemPage
from ...pages.lms.video.video import VideoPage
from ...pages.lms.courseware import CoursewarePage
+from ...pages.studio.settings import SettingsPage
from ...pages.lms.login_and_register import CombinedLoginAndRegisterPage
from ...pages.studio.settings import SettingsPage
from ...fixtures.course import CourseFixture, XBlockFixtureDesc, CourseUpdateDesc
@@ -771,3 +773,73 @@ class ProblemExecutionTest(UniqueCourseTest):
problem_page.fill_answer("4")
problem_page.click_check()
self.assertFalse(problem_page.is_correct())
+
+
+class EntranceExamTest(UniqueCourseTest):
+ """
+ Tests that course has an entrance exam.
+ """
+
+ def setUp(self):
+ """
+ Initialize pages and install a course fixture.
+ """
+ super(EntranceExamTest, self).setUp()
+
+ CourseFixture(
+ self.course_info['org'], self.course_info['number'],
+ self.course_info['run'], self.course_info['display_name']
+ ).install()
+
+ self.course_info_page = CourseInfoPage(self.browser, self.course_id)
+ self.settings_page = SettingsPage(
+ self.browser,
+ self.course_info['org'],
+ self.course_info['number'],
+ self.course_info['run']
+ )
+
+ # Auto-auth register for the course
+ AutoAuthPage(self.browser, course_id=self.course_id).visit()
+
+ def test_entrance_exam_section(self):
+ """
+ Scenario: Any course that is enabled for an entrance exam, should have entrance exam section at course info
+ page.
+ Given that I am on the course info page
+ When I view the course info that has an entrance exam
+ Then there should be an "Entrance Exam" section.'
+ """
+
+ # visit course info page and make sure there is not entrance exam section.
+ self.course_info_page.visit()
+ self.course_info_page.wait_for_page()
+ self.assertFalse(element_has_text(
+ page=self.course_info_page,
+ css_selector='div ol li a',
+ text='Entrance Exam'
+ ))
+
+ # Logout and login as a staff.
+ LogoutPage(self.browser).visit()
+ AutoAuthPage(self.browser, course_id=self.course_id, staff=True).visit()
+
+ # visit course settings page and set/enabled entrance exam for that course.
+ self.settings_page.visit()
+ self.settings_page.wait_for_page()
+ self.assertTrue(self.settings_page.is_browser_on_page())
+ self.settings_page.entrance_exam_field[0].click()
+ self.settings_page.save_changes()
+
+ # Logout and login as a student.
+ LogoutPage(self.browser).visit()
+ AutoAuthPage(self.browser, course_id=self.course_id, staff=False).visit()
+
+ # visit course info page and make sure there is an "Entrance Exam" section.
+ self.course_info_page.visit()
+ self.course_info_page.wait_for_page()
+ self.assertTrue(element_has_text(
+ page=self.course_info_page,
+ css_selector='div ol li a',
+ text='Entrance Exam'
+ ))
diff --git a/common/test/acceptance/tests/studio/test_studio_settings_details.py b/common/test/acceptance/tests/studio/test_studio_settings_details.py
index 6fd0225ca6..bbec1d875c 100644
--- a/common/test/acceptance/tests/studio/test_studio_settings_details.py
+++ b/common/test/acceptance/tests/studio/test_studio_settings_details.py
@@ -1,16 +1,20 @@
"""
Acceptance tests for Studio's Settings Details pages
"""
+from unittest import skip
+
from acceptance.tests.studio.base_studio_test import StudioCourseTest
from ...fixtures.course import CourseFixture
+from ...pages.studio.settings import SettingsPage
+from ...pages.studio.overview import CourseOutlinePage
+from ...tests.studio.base_studio_test import StudioCourseTest
from ..helpers import (
generate_course_key,
select_option_by_value,
- is_option_value_selected
+ is_option_value_selected,
+ element_has_text,
)
-from ...pages.studio.settings import SettingsPage
-
class SettingsMilestonesTest(StudioCourseTest):
"""
@@ -82,3 +86,43 @@ class SettingsMilestonesTest(StudioCourseTest):
self.settings_detail.save_changes()
self.assertTrue('Your changes have been saved.' in self.settings_detail.browser.page_source)
self.assertTrue(is_option_value_selected(browser_query=self.settings_detail.pre_requisite_course, value=''))
+
+ def test_page_has_enable_entrance_exam_field(self):
+ """
+ Test to make sure page has 'enable entrance exam' field.
+ """
+ self.assertTrue(self.settings_detail.entrance_exam_field)
+
+ @skip('Passes in devstack, passes individually in Jenkins, fails in suite in Jenkins.')
+ def test_enable_entrance_exam_for_course(self):
+ """
+ Test that entrance exam should be created after checking the 'enable entrance exam' checkbox.
+ And also that the entrance exam is destroyed after deselecting the checkbox.
+ """
+ self.settings_detail.require_entrance_exam(required=True)
+ self.settings_detail.save_changes()
+
+ # getting the course outline page.
+ course_outline_page = CourseOutlinePage(
+ self.browser, self.course_info['org'], self.course_info['number'], self.course_info['run']
+ )
+ course_outline_page.visit()
+
+ # title with text 'Entrance Exam' should be present on page.
+ self.assertTrue(element_has_text(
+ page=course_outline_page,
+ css_selector='span.section-title',
+ text='Entrance Exam'
+ ))
+
+ # Delete the currently created entrance exam.
+ self.settings_detail.visit()
+ self.settings_detail.require_entrance_exam(required=False)
+ self.settings_detail.save_changes()
+
+ course_outline_page.visit()
+ self.assertFalse(element_has_text(
+ page=course_outline_page,
+ css_selector='span.section-title',
+ text='Entrance Exam'
+ ))
diff --git a/common/test/db_cache/bok_choy_data.json b/common/test/db_cache/bok_choy_data.json
index 091f4ca99d..c112ae95e6 100644
--- a/common/test/db_cache/bok_choy_data.json
+++ b/common/test/db_cache/bok_choy_data.json
@@ -1 +1 @@
-[{"pk": 62, "model": "contenttypes.contenttype", "fields": {"model": "accesstoken", "name": "access token", "app_label": "oauth2"}}, {"pk": 131, "model": "contenttypes.contenttype", "fields": {"model": "aiclassifier", "name": "ai classifier", "app_label": "assessment"}}, {"pk": 130, "model": "contenttypes.contenttype", "fields": {"model": "aiclassifierset", "name": "ai classifier set", "app_label": "assessment"}}, {"pk": 133, "model": "contenttypes.contenttype", "fields": {"model": "aigradingworkflow", "name": "ai grading workflow", "app_label": "assessment"}}, {"pk": 132, "model": "contenttypes.contenttype", "fields": {"model": "aitrainingworkflow", "name": "ai training workflow", "app_label": "assessment"}}, {"pk": 33, "model": "contenttypes.contenttype", "fields": {"model": "anonymoususerid", "name": "anonymous user id", "app_label": "student"}}, {"pk": 112, "model": "contenttypes.contenttype", "fields": {"model": "answer", "name": "answer", "app_label": "mentoring"}}, {"pk": 65, "model": "contenttypes.contenttype", "fields": {"model": "article", "name": "article", "app_label": "wiki"}}, {"pk": 66, "model": "contenttypes.contenttype", "fields": {"model": "articleforobject", "name": "Article for object", "app_label": "wiki"}}, {"pk": 69, "model": "contenttypes.contenttype", "fields": {"model": "articleplugin", "name": "article plugin", "app_label": "wiki"}}, {"pk": 67, "model": "contenttypes.contenttype", "fields": {"model": "articlerevision", "name": "article revision", "app_label": "wiki"}}, {"pk": 74, "model": "contenttypes.contenttype", "fields": {"model": "articlesubscription", "name": "article subscription", "app_label": "wiki"}}, {"pk": 121, "model": "contenttypes.contenttype", "fields": {"model": "assessment", "name": "assessment", "app_label": "assessment"}}, {"pk": 124, "model": "contenttypes.contenttype", "fields": {"model": "assessmentfeedback", "name": "assessment feedback", "app_label": "assessment"}}, {"pk": 123, "model": "contenttypes.contenttype", "fields": {"model": "assessmentfeedbackoption", "name": "assessment feedback option", "app_label": "assessment"}}, {"pk": 122, "model": "contenttypes.contenttype", "fields": {"model": "assessmentpart", "name": "assessment part", "app_label": "assessment"}}, {"pk": 134, "model": "contenttypes.contenttype", "fields": {"model": "assessmentworkflow", "name": "assessment workflow", "app_label": "workflow"}}, {"pk": 135, "model": "contenttypes.contenttype", "fields": {"model": "assessmentworkflowstep", "name": "assessment workflow step", "app_label": "workflow"}}, {"pk": 19, "model": "contenttypes.contenttype", "fields": {"model": "association", "name": "association", "app_label": "django_openid_auth"}}, {"pk": 24, "model": "contenttypes.contenttype", "fields": {"model": "association", "name": "association", "app_label": "default"}}, {"pk": 97, "model": "contenttypes.contenttype", "fields": {"model": "certificateitem", "name": "certificate item", "app_label": "shoppingcart"}}, {"pk": 48, "model": "contenttypes.contenttype", "fields": {"model": "certificatewhitelist", "name": "certificate whitelist", "app_label": "certificates"}}, {"pk": 60, "model": "contenttypes.contenttype", "fields": {"model": "client", "name": "client", "app_label": "oauth2"}}, {"pk": 25, "model": "contenttypes.contenttype", "fields": {"model": "code", "name": "code", "app_label": "default"}}, {"pk": 4, "model": "contenttypes.contenttype", "fields": {"model": "contenttype", "name": "content type", "app_label": "contenttypes"}}, {"pk": 91, "model": "contenttypes.contenttype", "fields": {"model": "coupon", "name": "coupon", "app_label": "shoppingcart"}}, {"pk": 92, "model": "contenttypes.contenttype", "fields": {"model": "couponredemption", "name": "coupon redemption", "app_label": "shoppingcart"}}, {"pk": 45, "model": "contenttypes.contenttype", "fields": {"model": "courseaccessrole", "name": "course access role", "app_label": "student"}}, {"pk": 58, "model": "contenttypes.contenttype", "fields": {"model": "courseauthorization", "name": "course authorization", "app_label": "bulk_email"}}, {"pk": 144, "model": "contenttypes.contenttype", "fields": {"model": "coursecontentmilestone", "name": "course content milestone", "app_label": "milestones"}}, {"pk": 147, "model": "contenttypes.contenttype", "fields": {"model": "coursecreator", "name": "course creator", "app_label": "course_creators"}}, {"pk": 55, "model": "contenttypes.contenttype", "fields": {"model": "courseemail", "name": "course email", "app_label": "bulk_email"}}, {"pk": 57, "model": "contenttypes.contenttype", "fields": {"model": "courseemailtemplate", "name": "course email template", "app_label": "bulk_email"}}, {"pk": 43, "model": "contenttypes.contenttype", "fields": {"model": "courseenrollment", "name": "course enrollment", "app_label": "student"}}, {"pk": 44, "model": "contenttypes.contenttype", "fields": {"model": "courseenrollmentallowed", "name": "course enrollment allowed", "app_label": "student"}}, {"pk": 143, "model": "contenttypes.contenttype", "fields": {"model": "coursemilestone", "name": "course milestone", "app_label": "milestones"}}, {"pk": 100, "model": "contenttypes.contenttype", "fields": {"model": "coursemode", "name": "course mode", "app_label": "course_modes"}}, {"pk": 101, "model": "contenttypes.contenttype", "fields": {"model": "coursemodesarchive", "name": "course modes archive", "app_label": "course_modes"}}, {"pk": 94, "model": "contenttypes.contenttype", "fields": {"model": "courseregcodeitem", "name": "course reg code item", "app_label": "shoppingcart"}}, {"pk": 95, "model": "contenttypes.contenttype", "fields": {"model": "courseregcodeitemannotation", "name": "course reg code item annotation", "app_label": "shoppingcart"}}, {"pk": 89, "model": "contenttypes.contenttype", "fields": {"model": "courseregistrationcode", "name": "course registration code", "app_label": "shoppingcart"}}, {"pk": 108, "model": "contenttypes.contenttype", "fields": {"model": "coursererunstate", "name": "course rerun state", "app_label": "course_action_state"}}, {"pk": 51, "model": "contenttypes.contenttype", "fields": {"model": "coursesoftware", "name": "course software", "app_label": "licenses"}}, {"pk": 53, "model": "contenttypes.contenttype", "fields": {"model": "courseusergroup", "name": "course user group", "app_label": "course_groups"}}, {"pk": 54, "model": "contenttypes.contenttype", "fields": {"model": "courseusergrouppartitiongroup", "name": "course user group partition group", "app_label": "course_groups"}}, {"pk": 138, "model": "contenttypes.contenttype", "fields": {"model": "coursevideo", "name": "course video", "app_label": "edxval"}}, {"pk": 119, "model": "contenttypes.contenttype", "fields": {"model": "criterion", "name": "criterion", "app_label": "assessment"}}, {"pk": 120, "model": "contenttypes.contenttype", "fields": {"model": "criterionoption", "name": "criterion option", "app_label": "assessment"}}, {"pk": 10, "model": "contenttypes.contenttype", "fields": {"model": "crontabschedule", "name": "crontab", "app_label": "djcelery"}}, {"pk": 103, "model": "contenttypes.contenttype", "fields": {"model": "darklangconfig", "name": "dark lang config", "app_label": "dark_lang"}}, {"pk": 46, "model": "contenttypes.contenttype", "fields": {"model": "dashboardconfiguration", "name": "dashboard configuration", "app_label": "student"}}, {"pk": 99, "model": "contenttypes.contenttype", "fields": {"model": "donation", "name": "donation", "app_label": "shoppingcart"}}, {"pk": 98, "model": "contenttypes.contenttype", "fields": {"model": "donationconfiguration", "name": "donation configuration", "app_label": "shoppingcart"}}, {"pk": 105, "model": "contenttypes.contenttype", "fields": {"model": "embargoedcourse", "name": "embargoed course", "app_label": "embargo"}}, {"pk": 106, "model": "contenttypes.contenttype", "fields": {"model": "embargoedstate", "name": "embargoed state", "app_label": "embargo"}}, {"pk": 139, "model": "contenttypes.contenttype", "fields": {"model": "encodedvideo", "name": "encoded video", "app_label": "edxval"}}, {"pk": 59, "model": "contenttypes.contenttype", "fields": {"model": "externalauthmap", "name": "external auth map", "app_label": "external_auth"}}, {"pk": 49, "model": "contenttypes.contenttype", "fields": {"model": "generatedcertificate", "name": "generated certificate", "app_label": "certificates"}}, {"pk": 61, "model": "contenttypes.contenttype", "fields": {"model": "grant", "name": "grant", "app_label": "oauth2"}}, {"pk": 2, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "auth"}}, {"pk": 50, "model": "contenttypes.contenttype", "fields": {"model": "instructortask", "name": "instructor task", "app_label": "instructor_task"}}, {"pk": 9, "model": "contenttypes.contenttype", "fields": {"model": "intervalschedule", "name": "interval", "app_label": "djcelery"}}, {"pk": 88, "model": "contenttypes.contenttype", "fields": {"model": "invoice", "name": "invoice", "app_label": "shoppingcart"}}, {"pk": 107, "model": "contenttypes.contenttype", "fields": {"model": "ipfilter", "name": "ip filter", "app_label": "embargo"}}, {"pk": 113, "model": "contenttypes.contenttype", "fields": {"model": "lightchild", "name": "light child", "app_label": "mentoring"}}, {"pk": 21, "model": "contenttypes.contenttype", "fields": {"model": "logentry", "name": "log entry", "app_label": "admin"}}, {"pk": 42, "model": "contenttypes.contenttype", "fields": {"model": "loginfailures", "name": "login failures", "app_label": "student"}}, {"pk": 104, "model": "contenttypes.contenttype", "fields": {"model": "midcoursereverificationwindow", "name": "midcourse reverification window", "app_label": "reverification"}}, {"pk": 15, "model": "contenttypes.contenttype", "fields": {"model": "migrationhistory", "name": "migration history", "app_label": "south"}}, {"pk": 141, "model": "contenttypes.contenttype", "fields": {"model": "milestone", "name": "milestone", "app_label": "milestones"}}, {"pk": 142, "model": "contenttypes.contenttype", "fields": {"model": "milestonerelationshiptype", "name": "milestone relationship type", "app_label": "milestones"}}, {"pk": 18, "model": "contenttypes.contenttype", "fields": {"model": "nonce", "name": "nonce", "app_label": "django_openid_auth"}}, {"pk": 23, "model": "contenttypes.contenttype", "fields": {"model": "nonce", "name": "nonce", "app_label": "default"}}, {"pk": 81, "model": "contenttypes.contenttype", "fields": {"model": "note", "name": "note", "app_label": "notes"}}, {"pk": 78, "model": "contenttypes.contenttype", "fields": {"model": "notification", "name": "notification", "app_label": "django_notify"}}, {"pk": 31, "model": "contenttypes.contenttype", "fields": {"model": "offlinecomputedgrade", "name": "offline computed grade", "app_label": "courseware"}}, {"pk": 32, "model": "contenttypes.contenttype", "fields": {"model": "offlinecomputedgradelog", "name": "offline computed grade log", "app_label": "courseware"}}, {"pk": 56, "model": "contenttypes.contenttype", "fields": {"model": "optout", "name": "optout", "app_label": "bulk_email"}}, {"pk": 86, "model": "contenttypes.contenttype", "fields": {"model": "order", "name": "order", "app_label": "shoppingcart"}}, {"pk": 87, "model": "contenttypes.contenttype", "fields": {"model": "orderitem", "name": "order item", "app_label": "shoppingcart"}}, {"pk": 93, "model": "contenttypes.contenttype", "fields": {"model": "paidcourseregistration", "name": "paid course registration", "app_label": "shoppingcart"}}, {"pk": 96, "model": "contenttypes.contenttype", "fields": {"model": "paidcourseregistrationannotation", "name": "paid course registration annotation", "app_label": "shoppingcart"}}, {"pk": 41, "model": "contenttypes.contenttype", "fields": {"model": "passwordhistory", "name": "password history", "app_label": "student"}}, {"pk": 125, "model": "contenttypes.contenttype", "fields": {"model": "peerworkflow", "name": "peer workflow", "app_label": "assessment"}}, {"pk": 126, "model": "contenttypes.contenttype", "fields": {"model": "peerworkflowitem", "name": "peer workflow item", "app_label": "assessment"}}, {"pk": 40, "model": "contenttypes.contenttype", "fields": {"model": "pendingemailchange", "name": "pending email change", "app_label": "student"}}, {"pk": 39, "model": "contenttypes.contenttype", "fields": {"model": "pendingnamechange", "name": "pending name change", "app_label": "student"}}, {"pk": 12, "model": "contenttypes.contenttype", "fields": {"model": "periodictask", "name": "periodic task", "app_label": "djcelery"}}, {"pk": 11, "model": "contenttypes.contenttype", "fields": {"model": "periodictasks", "name": "periodic tasks", "app_label": "djcelery"}}, {"pk": 1, "model": "contenttypes.contenttype", "fields": {"model": "permission", "name": "permission", "app_label": "auth"}}, {"pk": 136, "model": "contenttypes.contenttype", "fields": {"model": "profile", "name": "profile", "app_label": "edxval"}}, {"pk": 17, "model": "contenttypes.contenttype", "fields": {"model": "psychometricdata", "name": "psychometric data", "app_label": "psychometrics"}}, {"pk": 80, "model": "contenttypes.contenttype", "fields": {"model": "puzzlecomplete", "name": "puzzle complete", "app_label": "foldit"}}, {"pk": 63, "model": "contenttypes.contenttype", "fields": {"model": "refreshtoken", "name": "refresh token", "app_label": "oauth2"}}, {"pk": 38, "model": "contenttypes.contenttype", "fields": {"model": "registration", "name": "registration", "app_label": "student"}}, {"pk": 90, "model": "contenttypes.contenttype", "fields": {"model": "registrationcoderedemption", "name": "registration code redemption", "app_label": "shoppingcart"}}, {"pk": 70, "model": "contenttypes.contenttype", "fields": {"model": "reusableplugin", "name": "reusable plugin", "app_label": "wiki"}}, {"pk": 72, "model": "contenttypes.contenttype", "fields": {"model": "revisionplugin", "name": "revision plugin", "app_label": "wiki"}}, {"pk": 73, "model": "contenttypes.contenttype", "fields": {"model": "revisionpluginrevision", "name": "revision plugin revision", "app_label": "wiki"}}, {"pk": 118, "model": "contenttypes.contenttype", "fields": {"model": "rubric", "name": "rubric", "app_label": "assessment"}}, {"pk": 8, "model": "contenttypes.contenttype", "fields": {"model": "tasksetmeta", "name": "saved group result", "app_label": "djcelery"}}, {"pk": 79, "model": "contenttypes.contenttype", "fields": {"model": "score", "name": "score", "app_label": "foldit"}}, {"pk": 116, "model": "contenttypes.contenttype", "fields": {"model": "score", "name": "score", "app_label": "submissions"}}, {"pk": 117, "model": "contenttypes.contenttype", "fields": {"model": "scoresummary", "name": "score summary", "app_label": "submissions"}}, {"pk": 16, "model": "contenttypes.contenttype", "fields": {"model": "servercircuit", "name": "server circuit", "app_label": "circuit"}}, {"pk": 5, "model": "contenttypes.contenttype", "fields": {"model": "session", "name": "session", "app_label": "sessions"}}, {"pk": 76, "model": "contenttypes.contenttype", "fields": {"model": "settings", "name": "settings", "app_label": "django_notify"}}, {"pk": 71, "model": "contenttypes.contenttype", "fields": {"model": "simpleplugin", "name": "simple plugin", "app_label": "wiki"}}, {"pk": 6, "model": "contenttypes.contenttype", "fields": {"model": "site", "name": "site", "app_label": "sites"}}, {"pk": 102, "model": "contenttypes.contenttype", "fields": {"model": "softwaresecurephotoverification", "name": "software secure photo verification", "app_label": "verify_student"}}, {"pk": 82, "model": "contenttypes.contenttype", "fields": {"model": "splashconfig", "name": "splash config", "app_label": "splash"}}, {"pk": 114, "model": "contenttypes.contenttype", "fields": {"model": "studentitem", "name": "student item", "app_label": "submissions"}}, {"pk": 26, "model": "contenttypes.contenttype", "fields": {"model": "studentmodule", "name": "student module", "app_label": "courseware"}}, {"pk": 27, "model": "contenttypes.contenttype", "fields": {"model": "studentmodulehistory", "name": "student module history", "app_label": "courseware"}}, {"pk": 128, "model": "contenttypes.contenttype", "fields": {"model": "studenttrainingworkflow", "name": "student training workflow", "app_label": "assessment"}}, {"pk": 129, "model": "contenttypes.contenttype", "fields": {"model": "studenttrainingworkflowitem", "name": "student training workflow item", "app_label": "assessment"}}, {"pk": 148, "model": "contenttypes.contenttype", "fields": {"model": "studioconfig", "name": "studio config", "app_label": "xblock_config"}}, {"pk": 115, "model": "contenttypes.contenttype", "fields": {"model": "submission", "name": "submission", "app_label": "submissions"}}, {"pk": 77, "model": "contenttypes.contenttype", "fields": {"model": "subscription", "name": "subscription", "app_label": "django_notify"}}, {"pk": 140, "model": "contenttypes.contenttype", "fields": {"model": "subtitle", "name": "subtitle", "app_label": "edxval"}}, {"pk": 110, "model": "contenttypes.contenttype", "fields": {"model": "surveyanswer", "name": "survey answer", "app_label": "survey"}}, {"pk": 109, "model": "contenttypes.contenttype", "fields": {"model": "surveyform", "name": "survey form", "app_label": "survey"}}, {"pk": 14, "model": "contenttypes.contenttype", "fields": {"model": "taskstate", "name": "task", "app_label": "djcelery"}}, {"pk": 7, "model": "contenttypes.contenttype", "fields": {"model": "taskmeta", "name": "task state", "app_label": "djcelery"}}, {"pk": 47, "model": "contenttypes.contenttype", "fields": {"model": "trackinglog", "name": "tracking log", "app_label": "track"}}, {"pk": 127, "model": "contenttypes.contenttype", "fields": {"model": "trainingexample", "name": "training example", "app_label": "assessment"}}, {"pk": 64, "model": "contenttypes.contenttype", "fields": {"model": "trustedclient", "name": "trusted client", "app_label": "oauth2_provider"}}, {"pk": 75, "model": "contenttypes.contenttype", "fields": {"model": "notificationtype", "name": "type", "app_label": "django_notify"}}, {"pk": 68, "model": "contenttypes.contenttype", "fields": {"model": "urlpath", "name": "URL path", "app_label": "wiki"}}, {"pk": 3, "model": "contenttypes.contenttype", "fields": {"model": "user", "name": "user", "app_label": "auth"}}, {"pk": 84, "model": "contenttypes.contenttype", "fields": {"model": "usercoursetag", "name": "user course tag", "app_label": "user_api"}}, {"pk": 52, "model": "contenttypes.contenttype", "fields": {"model": "userlicense", "name": "user license", "app_label": "licenses"}}, {"pk": 145, "model": "contenttypes.contenttype", "fields": {"model": "usermilestone", "name": "user milestone", "app_label": "milestones"}}, {"pk": 20, "model": "contenttypes.contenttype", "fields": {"model": "useropenid", "name": "user open id", "app_label": "django_openid_auth"}}, {"pk": 85, "model": "contenttypes.contenttype", "fields": {"model": "userorgtag", "name": "user org tag", "app_label": "user_api"}}, {"pk": 83, "model": "contenttypes.contenttype", "fields": {"model": "userpreference", "name": "user preference", "app_label": "user_api"}}, {"pk": 35, "model": "contenttypes.contenttype", "fields": {"model": "userprofile", "name": "user profile", "app_label": "student"}}, {"pk": 36, "model": "contenttypes.contenttype", "fields": {"model": "usersignupsource", "name": "user signup source", "app_label": "student"}}, {"pk": 22, "model": "contenttypes.contenttype", "fields": {"model": "usersocialauth", "name": "user social auth", "app_label": "default"}}, {"pk": 34, "model": "contenttypes.contenttype", "fields": {"model": "userstanding", "name": "user standing", "app_label": "student"}}, {"pk": 37, "model": "contenttypes.contenttype", "fields": {"model": "usertestgroup", "name": "user test group", "app_label": "student"}}, {"pk": 137, "model": "contenttypes.contenttype", "fields": {"model": "video", "name": "video", "app_label": "edxval"}}, {"pk": 146, "model": "contenttypes.contenttype", "fields": {"model": "videouploadconfig", "name": "video upload config", "app_label": "contentstore"}}, {"pk": 13, "model": "contenttypes.contenttype", "fields": {"model": "workerstate", "name": "worker", "app_label": "djcelery"}}, {"pk": 111, "model": "contenttypes.contenttype", "fields": {"model": "xblockasidesconfig", "name": "x block asides config", "app_label": "lms_xblock"}}, {"pk": 30, "model": "contenttypes.contenttype", "fields": {"model": "xmodulestudentinfofield", "name": "x module student info field", "app_label": "courseware"}}, {"pk": 29, "model": "contenttypes.contenttype", "fields": {"model": "xmodulestudentprefsfield", "name": "x module student prefs field", "app_label": "courseware"}}, {"pk": 28, "model": "contenttypes.contenttype", "fields": {"model": "xmoduleuserstatesummaryfield", "name": "x module user state summary field", "app_label": "courseware"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 1, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0001_initial"}}, {"pk": 2, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0002_add_indexes"}}, {"pk": 3, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0003_done_grade_cache"}}, {"pk": 4, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0004_add_field_studentmodule_course_id"}}, {"pk": 5, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c"}}, {"pk": 6, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0006_create_student_module_history"}}, {"pk": 7, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0007_allow_null_version_in_history"}}, {"pk": 8, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0008_add_xmodule_storage"}}, {"pk": 9, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0009_add_field_default"}}, {"pk": 10, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0010_rename_xblock_field_content_to_user_state_summary"}}, {"pk": 11, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "student", "migration": "0001_initial"}}, {"pk": 12, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "student", "migration": "0002_text_to_varchar_and_indexes"}}, {"pk": 13, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0003_auto__add_usertestgroup"}}, {"pk": 14, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0004_add_email_index"}}, {"pk": 15, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0005_name_change"}}, {"pk": 16, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0006_expand_meta_field"}}, {"pk": 17, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0007_convert_to_utf8"}}, {"pk": 18, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0008__auto__add_courseregistration"}}, {"pk": 19, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0009_auto__del_courseregistration__add_courseenrollment"}}, {"pk": 20, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0010_auto__chg_field_courseenrollment_course_id"}}, {"pk": 21, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0011_auto__chg_field_courseenrollment_user__del_unique_courseenrollment_use"}}, {"pk": 22, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0012_auto__add_field_userprofile_gender__add_field_userprofile_date_of_birt"}}, {"pk": 23, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0013_auto__chg_field_userprofile_meta"}}, {"pk": 24, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0014_auto__del_courseenrollment"}}, {"pk": 25, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0015_auto__add_courseenrollment__add_unique_courseenrollment_user_course_id"}}, {"pk": 26, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0016_auto__add_field_courseenrollment_date__chg_field_userprofile_country"}}, {"pk": 27, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0017_rename_date_to_created"}}, {"pk": 28, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0018_auto"}}, {"pk": 29, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0019_create_approved_demographic_fields_fall_2012"}}, {"pk": 30, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0020_add_test_center_user"}}, {"pk": 31, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0021_remove_askbot"}}, {"pk": 32, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_"}}, {"pk": 33, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0023_add_test_center_registration"}}, {"pk": 34, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0024_add_allow_certificate"}}, {"pk": 35, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0025_auto__add_field_courseenrollmentallowed_auto_enroll"}}, {"pk": 36, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0026_auto__remove_index_student_testcenterregistration_accommodation_request"}}, {"pk": 37, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0027_add_active_flag_and_mode_to_courseware_enrollment"}}, {"pk": 38, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0028_auto__add_userstanding"}}, {"pk": 39, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0029_add_lookup_table_between_user_and_anonymous_student_id"}}, {"pk": 40, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0029_remove_pearson"}}, {"pk": 41, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0030_auto__chg_field_anonymoususerid_anonymous_user_id"}}, {"pk": 42, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0031_drop_student_anonymoususerid_temp_archive"}}, {"pk": 43, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0032_add_field_UserProfile_country_add_field_UserProfile_city"}}, {"pk": 44, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0032_auto__add_loginfailures"}}, {"pk": 45, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0033_auto__add_passwordhistory"}}, {"pk": 46, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0034_auto__add_courseaccessrole"}}, {"pk": 47, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0035_access_roles"}}, {"pk": 48, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0036_access_roles_orgless"}}, {"pk": 49, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0037_auto__add_courseregistrationcode"}}, {"pk": 50, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0038_auto__add_usersignupsource"}}, {"pk": 51, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0039_auto__del_courseregistrationcode"}}, {"pk": 52, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0040_auto__del_field_usersignupsource_user_id__add_field_usersignupsource_u"}}, {"pk": 53, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0041_add_dashboard_config"}}, {"pk": 54, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0042_grant_sales_admin_roles"}}, {"pk": 55, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "track", "migration": "0001_initial"}}, {"pk": 56, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "track", "migration": "0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch"}}, {"pk": 57, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0001_added_generatedcertificates"}}, {"pk": 58, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0002_auto__add_field_generatedcertificate_download_url"}}, {"pk": 59, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0003_auto__add_field_generatedcertificate_enabled"}}, {"pk": 60, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0004_auto__add_field_generatedcertificate_graded_certificate_id__add_field_"}}, {"pk": 61, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0005_auto__add_field_generatedcertificate_name"}}, {"pk": 62, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0006_auto__chg_field_generatedcertificate_certificate_id"}}, {"pk": 63, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0007_auto__add_revokedcertificate"}}, {"pk": 64, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add"}}, {"pk": 65, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge"}}, {"pk": 66, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti"}}, {"pk": 67, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat"}}, {"pk": 68, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific"}}, {"pk": 69, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0013_auto__add_field_generatedcertificate_error_reason"}}, {"pk": 70, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0014_adding_whitelist"}}, {"pk": 71, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0015_adding_mode_for_verified_certs"}}, {"pk": 72, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "instructor_task", "migration": "0001_initial"}}, {"pk": 73, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "instructor_task", "migration": "0002_add_subtask_field"}}, {"pk": 74, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "licenses", "migration": "0001_initial"}}, {"pk": 75, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "course_groups", "migration": "0001_initial"}}, {"pk": 76, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "course_groups", "migration": "0002_add_model_CourseUserGroupPartitionGroup"}}, {"pk": 77, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0001_initial"}}, {"pk": 78, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0002_change_field_names"}}, {"pk": 79, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0003_add_optout_user"}}, {"pk": 80, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0004_migrate_optout_user"}}, {"pk": 81, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0005_remove_optout_email"}}, {"pk": 82, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0006_add_course_email_template"}}, {"pk": 83, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0007_load_course_email_template"}}, {"pk": 84, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0008_add_course_authorizations"}}, {"pk": 85, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0009_force_unique_course_ids"}}, {"pk": 86, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0010_auto__chg_field_optout_course_id__add_field_courseemail_template_name_"}}, {"pk": 87, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "external_auth", "migration": "0001_initial"}}, {"pk": 88, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0001_initial"}}, {"pk": 89, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0002_auto__chg_field_client_user"}}, {"pk": 90, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0003_auto__add_field_client_name"}}, {"pk": 91, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0004_auto__add_index_accesstoken_token"}}, {"pk": 92, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2_provider", "migration": "0001_initial"}}, {"pk": 93, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0001_initial"}}, {"pk": 94, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0002_auto__add_field_articleplugin_created"}}, {"pk": 95, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0003_auto__add_field_urlpath_article"}}, {"pk": 96, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0004_populate_urlpath__article"}}, {"pk": 97, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0005_auto__chg_field_urlpath_article"}}, {"pk": 98, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0006_auto__add_attachmentrevision__add_image__add_attachment"}}, {"pk": 99, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0007_auto__add_articlesubscription"}}, {"pk": 100, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0008_auto__add_simpleplugin__add_revisionpluginrevision__add_imagerevision_"}}, {"pk": 101, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0009_auto__add_field_imagerevision_width__add_field_imagerevision_height"}}, {"pk": 102, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0010_auto__chg_field_imagerevision_image"}}, {"pk": 103, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0011_auto__chg_field_imagerevision_width__chg_field_imagerevision_height"}}, {"pk": 104, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "django_notify", "migration": "0001_initial"}}, {"pk": 105, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "notifications", "migration": "0001_initial"}}, {"pk": 106, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "foldit", "migration": "0001_initial"}}, {"pk": 107, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:28Z", "app_name": "django_comment_client", "migration": "0001_initial"}}, {"pk": 108, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:28Z", "app_name": "django_comment_common", "migration": "0001_initial"}}, {"pk": 109, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "notes", "migration": "0001_initial"}}, {"pk": 110, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "splash", "migration": "0001_initial"}}, {"pk": 111, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "splash", "migration": "0002_auto__add_field_splashconfig_unaffected_url_paths"}}, {"pk": 112, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "user_api", "migration": "0001_initial"}}, {"pk": 113, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0002_auto__add_usercoursetags__add_unique_usercoursetags_user_course_id_key"}}, {"pk": 114, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0003_rename_usercoursetags"}}, {"pk": 115, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0004_auto__add_userorgtag__add_unique_userorgtag_user_org_key__chg_field_us"}}, {"pk": 116, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0001_initial"}}, {"pk": 117, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0002_auto__add_field_paidcourseregistration_mode"}}, {"pk": 118, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0003_auto__del_field_orderitem_line_cost"}}, {"pk": 119, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0004_auto__add_field_orderitem_fulfilled_time"}}, {"pk": 120, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0005_auto__add_paidcourseregistrationannotation__add_field_orderitem_report"}}, {"pk": 121, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0006_auto__add_field_order_refunded_time__add_field_orderitem_refund_reques"}}, {"pk": 122, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0007_auto__add_field_orderitem_service_fee"}}, {"pk": 123, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0008_auto__add_coupons__add_couponredemption__chg_field_certificateitem_cou"}}, {"pk": 124, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0009_auto__del_coupons__add_courseregistrationcode__add_coupon__chg_field_c"}}, {"pk": 125, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0010_auto__add_registrationcoderedemption__del_field_courseregistrationcode"}}, {"pk": 126, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0011_auto__add_invoice__add_field_courseregistrationcode_invoice"}}, {"pk": 127, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0012_auto__del_field_courseregistrationcode_transaction_group_name__del_fie"}}, {"pk": 128, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0013_auto__add_field_invoice_is_valid"}}, {"pk": 129, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0014_auto__del_field_invoice_tax_id__add_field_invoice_address_line_1__add_"}}, {"pk": 130, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0015_auto__del_field_invoice_purchase_order_number__del_field_invoice_compa"}}, {"pk": 131, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0016_auto__del_field_invoice_company_email__del_field_invoice_company_refer"}}, {"pk": 132, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0017_auto__add_field_courseregistrationcode_order__chg_field_registrationco"}}, {"pk": 133, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0018_auto__add_donation"}}, {"pk": 134, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0019_auto__add_donationconfiguration"}}, {"pk": 135, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0020_auto__add_courseregcodeitem__add_courseregcodeitemannotation__add_fiel"}}, {"pk": 136, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0021_auto__add_field_orderitem_created__add_field_orderitem_modified"}}, {"pk": 137, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0022_auto__add_field_registrationcoderedemption_course_enrollment__add_fiel"}}, {"pk": 138, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0023_auto__add_field_coupon_expiration_date"}}, {"pk": 139, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0024_auto__add_field_courseregistrationcode_mode_slug"}}, {"pk": 140, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0001_initial"}}, {"pk": 141, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0002_auto__add_field_coursemode_currency"}}, {"pk": 142, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0003_auto__add_unique_coursemode_course_id_currency_mode_slug"}}, {"pk": 143, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0004_auto__add_field_coursemode_expiration_date"}}, {"pk": 144, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0005_auto__add_field_coursemode_expiration_datetime"}}, {"pk": 145, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0006_expiration_date_to_datetime"}}, {"pk": 146, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0007_add_description"}}, {"pk": 147, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0007_auto__add_coursemodesarchive__chg_field_coursemode_course_id"}}, {"pk": 148, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0001_initial"}}, {"pk": 149, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0002_auto__add_field_softwaresecurephotoverification_window"}}, {"pk": 150, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0003_auto__add_field_softwaresecurephotoverification_display"}}, {"pk": 151, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "dark_lang", "migration": "0001_initial"}}, {"pk": 152, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "dark_lang", "migration": "0002_enable_on_install"}}, {"pk": 153, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "reverification", "migration": "0001_initial"}}, {"pk": 154, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "embargo", "migration": "0001_initial"}}, {"pk": 155, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "course_action_state", "migration": "0001_initial"}}, {"pk": 156, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "course_action_state", "migration": "0002_add_rerun_display_name"}}, {"pk": 157, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "survey", "migration": "0001_initial"}}, {"pk": 158, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "lms_xblock", "migration": "0001_initial"}}, {"pk": 159, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0001_initial"}}, {"pk": 160, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0002_auto__add_field_answer_course_id__chg_field_answer_student_id"}}, {"pk": 161, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0003_auto__del_unique_answer_student_id_name__add_unique_answer_course_id_s"}}, {"pk": 162, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0004_auto__add_lightchild__add_unique_lightchild_student_id_course_id_name"}}, {"pk": 163, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0005_auto__chg_field_lightchild_name"}}, {"pk": 164, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0001_initial"}}, {"pk": 165, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0002_auto__add_scoresummary"}}, {"pk": 166, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0003_auto__del_field_submission_answer__add_field_submission_raw_answer"}}, {"pk": 167, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0004_auto__add_field_score_reset"}}, {"pk": 168, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0001_initial"}}, {"pk": 169, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0002_auto__add_assessmentfeedbackoption__del_field_assessmentfeedback_feedb"}}, {"pk": 170, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0003_add_index_pw_course_item_student"}}, {"pk": 171, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0004_auto__add_field_peerworkflow_graded_count"}}, {"pk": 172, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0005_auto__del_field_peerworkflow_graded_count__add_field_peerworkflow_grad"}}, {"pk": 173, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0006_auto__add_field_assessmentpart_feedback"}}, {"pk": 174, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0007_auto__chg_field_assessmentpart_feedback"}}, {"pk": 175, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0008_student_training"}}, {"pk": 176, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0009_auto__add_unique_studenttrainingworkflowitem_order_num_workflow"}}, {"pk": 177, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0010_auto__add_unique_studenttrainingworkflow_submission_uuid"}}, {"pk": 178, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0011_ai_training"}}, {"pk": 179, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0012_move_algorithm_id_to_classifier_set"}}, {"pk": 180, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0013_auto__add_field_aigradingworkflow_essay_text"}}, {"pk": 181, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0014_auto__add_field_aitrainingworkflow_item_id__add_field_aitrainingworkfl"}}, {"pk": 182, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0015_auto__add_unique_aitrainingworkflow_uuid__add_unique_aigradingworkflow"}}, {"pk": 183, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0016_auto__add_field_aiclassifierset_course_id__add_field_aiclassifierset_i"}}, {"pk": 184, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0016_auto__add_field_rubric_structure_hash"}}, {"pk": 185, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0017_rubric_structure_hash"}}, {"pk": 186, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0018_auto__add_field_assessmentpart_criterion"}}, {"pk": 187, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0019_assessmentpart_criterion_field"}}, {"pk": 188, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0020_assessmentpart_criterion_not_null"}}, {"pk": 189, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0021_assessmentpart_option_nullable"}}, {"pk": 190, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0022__add_label_fields"}}, {"pk": 191, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0023_assign_criteria_and_option_labels"}}, {"pk": 192, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "assessment", "migration": "0024_auto__chg_field_assessmentpart_criterion"}}, {"pk": 193, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0001_initial"}}, {"pk": 194, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0002_auto__add_field_assessmentworkflow_course_id__add_field_assessmentwork"}}, {"pk": 195, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0003_auto__add_assessmentworkflowstep"}}, {"pk": 196, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "edxval", "migration": "0001_initial"}}, {"pk": 197, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "edxval", "migration": "0002_default_profiles"}}, {"pk": 198, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "edxval", "migration": "0003_status_and_created_fields"}}, {"pk": 199, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "milestones", "migration": "0001_initial"}}, {"pk": 200, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "milestones", "migration": "0002_seed_relationship_types"}}, {"pk": 201, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "django_extensions", "migration": "0001_empty"}}, {"pk": 202, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "contentstore", "migration": "0001_initial"}}, {"pk": 203, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "course_creators", "migration": "0001_initial"}}, {"pk": 204, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "xblock_config", "migration": "0001_initial"}}, {"pk": 1, "model": "edxval.profile", "fields": {"width": 1280, "profile_name": "desktop_mp4", "extension": "mp4", "height": 720}}, {"pk": 2, "model": "edxval.profile", "fields": {"width": 1280, "profile_name": "desktop_webm", "extension": "webm", "height": 720}}, {"pk": 3, "model": "edxval.profile", "fields": {"width": 960, "profile_name": "mobile_high", "extension": "mp4", "height": 540}}, {"pk": 4, "model": "edxval.profile", "fields": {"width": 640, "profile_name": "mobile_low", "extension": "mp4", "height": 360}}, {"pk": 5, "model": "edxval.profile", "fields": {"width": 1920, "profile_name": "youtube", "extension": "mp4", "height": 1080}}, {"pk": 1, "model": "milestones.milestonerelationshiptype", "fields": {"active": true, "description": "Autogenerated milestone relationship type \"fulfills\"", "modified": "2015-01-15T03:15:43Z", "name": "fulfills", "created": "2015-01-15T03:15:43Z"}}, {"pk": 2, "model": "milestones.milestonerelationshiptype", "fields": {"active": true, "description": "Autogenerated milestone relationship type \"requires\"", "modified": "2015-01-15T03:15:43Z", "name": "requires", "created": "2015-01-15T03:15:43Z"}}, {"pk": 61, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 21}}, {"pk": 62, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 21}}, {"pk": 63, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 21}}, {"pk": 394, "model": "auth.permission", "fields": {"codename": "add_aiclassifier", "name": "Can add ai classifier", "content_type": 131}}, {"pk": 395, "model": "auth.permission", "fields": {"codename": "change_aiclassifier", "name": "Can change ai classifier", "content_type": 131}}, {"pk": 396, "model": "auth.permission", "fields": {"codename": "delete_aiclassifier", "name": "Can delete ai classifier", "content_type": 131}}, {"pk": 391, "model": "auth.permission", "fields": {"codename": "add_aiclassifierset", "name": "Can add ai classifier set", "content_type": 130}}, {"pk": 392, "model": "auth.permission", "fields": {"codename": "change_aiclassifierset", "name": "Can change ai classifier set", "content_type": 130}}, {"pk": 393, "model": "auth.permission", "fields": {"codename": "delete_aiclassifierset", "name": "Can delete ai classifier set", "content_type": 130}}, {"pk": 400, "model": "auth.permission", "fields": {"codename": "add_aigradingworkflow", "name": "Can add ai grading workflow", "content_type": 133}}, {"pk": 401, "model": "auth.permission", "fields": {"codename": "change_aigradingworkflow", "name": "Can change ai grading workflow", "content_type": 133}}, {"pk": 402, "model": "auth.permission", "fields": {"codename": "delete_aigradingworkflow", "name": "Can delete ai grading workflow", "content_type": 133}}, {"pk": 397, "model": "auth.permission", "fields": {"codename": "add_aitrainingworkflow", "name": "Can add ai training workflow", "content_type": 132}}, {"pk": 398, "model": "auth.permission", "fields": {"codename": "change_aitrainingworkflow", "name": "Can change ai training workflow", "content_type": 132}}, {"pk": 399, "model": "auth.permission", "fields": {"codename": "delete_aitrainingworkflow", "name": "Can delete ai training workflow", "content_type": 132}}, {"pk": 364, "model": "auth.permission", "fields": {"codename": "add_assessment", "name": "Can add assessment", "content_type": 121}}, {"pk": 365, "model": "auth.permission", "fields": {"codename": "change_assessment", "name": "Can change assessment", "content_type": 121}}, {"pk": 366, "model": "auth.permission", "fields": {"codename": "delete_assessment", "name": "Can delete assessment", "content_type": 121}}, {"pk": 373, "model": "auth.permission", "fields": {"codename": "add_assessmentfeedback", "name": "Can add assessment feedback", "content_type": 124}}, {"pk": 374, "model": "auth.permission", "fields": {"codename": "change_assessmentfeedback", "name": "Can change assessment feedback", "content_type": 124}}, {"pk": 375, "model": "auth.permission", "fields": {"codename": "delete_assessmentfeedback", "name": "Can delete assessment feedback", "content_type": 124}}, {"pk": 370, "model": "auth.permission", "fields": {"codename": "add_assessmentfeedbackoption", "name": "Can add assessment feedback option", "content_type": 123}}, {"pk": 371, "model": "auth.permission", "fields": {"codename": "change_assessmentfeedbackoption", "name": "Can change assessment feedback option", "content_type": 123}}, {"pk": 372, "model": "auth.permission", "fields": {"codename": "delete_assessmentfeedbackoption", "name": "Can delete assessment feedback option", "content_type": 123}}, {"pk": 367, "model": "auth.permission", "fields": {"codename": "add_assessmentpart", "name": "Can add assessment part", "content_type": 122}}, {"pk": 368, "model": "auth.permission", "fields": {"codename": "change_assessmentpart", "name": "Can change assessment part", "content_type": 122}}, {"pk": 369, "model": "auth.permission", "fields": {"codename": "delete_assessmentpart", "name": "Can delete assessment part", "content_type": 122}}, {"pk": 358, "model": "auth.permission", "fields": {"codename": "add_criterion", "name": "Can add criterion", "content_type": 119}}, {"pk": 359, "model": "auth.permission", "fields": {"codename": "change_criterion", "name": "Can change criterion", "content_type": 119}}, {"pk": 360, "model": "auth.permission", "fields": {"codename": "delete_criterion", "name": "Can delete criterion", "content_type": 119}}, {"pk": 361, "model": "auth.permission", "fields": {"codename": "add_criterionoption", "name": "Can add criterion option", "content_type": 120}}, {"pk": 362, "model": "auth.permission", "fields": {"codename": "change_criterionoption", "name": "Can change criterion option", "content_type": 120}}, {"pk": 363, "model": "auth.permission", "fields": {"codename": "delete_criterionoption", "name": "Can delete criterion option", "content_type": 120}}, {"pk": 376, "model": "auth.permission", "fields": {"codename": "add_peerworkflow", "name": "Can add peer workflow", "content_type": 125}}, {"pk": 377, "model": "auth.permission", "fields": {"codename": "change_peerworkflow", "name": "Can change peer workflow", "content_type": 125}}, {"pk": 378, "model": "auth.permission", "fields": {"codename": "delete_peerworkflow", "name": "Can delete peer workflow", "content_type": 125}}, {"pk": 379, "model": "auth.permission", "fields": {"codename": "add_peerworkflowitem", "name": "Can add peer workflow item", "content_type": 126}}, {"pk": 380, "model": "auth.permission", "fields": {"codename": "change_peerworkflowitem", "name": "Can change peer workflow item", "content_type": 126}}, {"pk": 381, "model": "auth.permission", "fields": {"codename": "delete_peerworkflowitem", "name": "Can delete peer workflow item", "content_type": 126}}, {"pk": 355, "model": "auth.permission", "fields": {"codename": "add_rubric", "name": "Can add rubric", "content_type": 118}}, {"pk": 356, "model": "auth.permission", "fields": {"codename": "change_rubric", "name": "Can change rubric", "content_type": 118}}, {"pk": 357, "model": "auth.permission", "fields": {"codename": "delete_rubric", "name": "Can delete rubric", "content_type": 118}}, {"pk": 385, "model": "auth.permission", "fields": {"codename": "add_studenttrainingworkflow", "name": "Can add student training workflow", "content_type": 128}}, {"pk": 386, "model": "auth.permission", "fields": {"codename": "change_studenttrainingworkflow", "name": "Can change student training workflow", "content_type": 128}}, {"pk": 387, "model": "auth.permission", "fields": {"codename": "delete_studenttrainingworkflow", "name": "Can delete student training workflow", "content_type": 128}}, {"pk": 388, "model": "auth.permission", "fields": {"codename": "add_studenttrainingworkflowitem", "name": "Can add student training workflow item", "content_type": 129}}, {"pk": 389, "model": "auth.permission", "fields": {"codename": "change_studenttrainingworkflowitem", "name": "Can change student training workflow item", "content_type": 129}}, {"pk": 390, "model": "auth.permission", "fields": {"codename": "delete_studenttrainingworkflowitem", "name": "Can delete student training workflow item", "content_type": 129}}, {"pk": 382, "model": "auth.permission", "fields": {"codename": "add_trainingexample", "name": "Can add training example", "content_type": 127}}, {"pk": 383, "model": "auth.permission", "fields": {"codename": "change_trainingexample", "name": "Can change training example", "content_type": 127}}, {"pk": 384, "model": "auth.permission", "fields": {"codename": "delete_trainingexample", "name": "Can delete training example", "content_type": 127}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 172, "model": "auth.permission", "fields": {"codename": "add_courseauthorization", "name": "Can add course authorization", "content_type": 58}}, {"pk": 173, "model": "auth.permission", "fields": {"codename": "change_courseauthorization", "name": "Can change course authorization", "content_type": 58}}, {"pk": 174, "model": "auth.permission", "fields": {"codename": "delete_courseauthorization", "name": "Can delete course authorization", "content_type": 58}}, {"pk": 163, "model": "auth.permission", "fields": {"codename": "add_courseemail", "name": "Can add course email", "content_type": 55}}, {"pk": 164, "model": "auth.permission", "fields": {"codename": "change_courseemail", "name": "Can change course email", "content_type": 55}}, {"pk": 165, "model": "auth.permission", "fields": {"codename": "delete_courseemail", "name": "Can delete course email", "content_type": 55}}, {"pk": 169, "model": "auth.permission", "fields": {"codename": "add_courseemailtemplate", "name": "Can add course email template", "content_type": 57}}, {"pk": 170, "model": "auth.permission", "fields": {"codename": "change_courseemailtemplate", "name": "Can change course email template", "content_type": 57}}, {"pk": 171, "model": "auth.permission", "fields": {"codename": "delete_courseemailtemplate", "name": "Can delete course email template", "content_type": 57}}, {"pk": 166, "model": "auth.permission", "fields": {"codename": "add_optout", "name": "Can add optout", "content_type": 56}}, {"pk": 167, "model": "auth.permission", "fields": {"codename": "change_optout", "name": "Can change optout", "content_type": 56}}, {"pk": 168, "model": "auth.permission", "fields": {"codename": "delete_optout", "name": "Can delete optout", "content_type": 56}}, {"pk": 142, "model": "auth.permission", "fields": {"codename": "add_certificatewhitelist", "name": "Can add certificate whitelist", "content_type": 48}}, {"pk": 143, "model": "auth.permission", "fields": {"codename": "change_certificatewhitelist", "name": "Can change certificate whitelist", "content_type": 48}}, {"pk": 144, "model": "auth.permission", "fields": {"codename": "delete_certificatewhitelist", "name": "Can delete certificate whitelist", "content_type": 48}}, {"pk": 145, "model": "auth.permission", "fields": {"codename": "add_generatedcertificate", "name": "Can add generated certificate", "content_type": 49}}, {"pk": 146, "model": "auth.permission", "fields": {"codename": "change_generatedcertificate", "name": "Can change generated certificate", "content_type": 49}}, {"pk": 147, "model": "auth.permission", "fields": {"codename": "delete_generatedcertificate", "name": "Can delete generated certificate", "content_type": 49}}, {"pk": 46, "model": "auth.permission", "fields": {"codename": "add_servercircuit", "name": "Can add server circuit", "content_type": 16}}, {"pk": 47, "model": "auth.permission", "fields": {"codename": "change_servercircuit", "name": "Can change server circuit", "content_type": 16}}, {"pk": 48, "model": "auth.permission", "fields": {"codename": "delete_servercircuit", "name": "Can delete server circuit", "content_type": 16}}, {"pk": 439, "model": "auth.permission", "fields": {"codename": "add_videouploadconfig", "name": "Can add video upload config", "content_type": 146}}, {"pk": 440, "model": "auth.permission", "fields": {"codename": "change_videouploadconfig", "name": "Can change video upload config", "content_type": 146}}, {"pk": 441, "model": "auth.permission", "fields": {"codename": "delete_videouploadconfig", "name": "Can delete video upload config", "content_type": 146}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 4}}, {"pk": 91, "model": "auth.permission", "fields": {"codename": "add_offlinecomputedgrade", "name": "Can add offline computed grade", "content_type": 31}}, {"pk": 92, "model": "auth.permission", "fields": {"codename": "change_offlinecomputedgrade", "name": "Can change offline computed grade", "content_type": 31}}, {"pk": 93, "model": "auth.permission", "fields": {"codename": "delete_offlinecomputedgrade", "name": "Can delete offline computed grade", "content_type": 31}}, {"pk": 94, "model": "auth.permission", "fields": {"codename": "add_offlinecomputedgradelog", "name": "Can add offline computed grade log", "content_type": 32}}, {"pk": 95, "model": "auth.permission", "fields": {"codename": "change_offlinecomputedgradelog", "name": "Can change offline computed grade log", "content_type": 32}}, {"pk": 96, "model": "auth.permission", "fields": {"codename": "delete_offlinecomputedgradelog", "name": "Can delete offline computed grade log", "content_type": 32}}, {"pk": 76, "model": "auth.permission", "fields": {"codename": "add_studentmodule", "name": "Can add student module", "content_type": 26}}, {"pk": 77, "model": "auth.permission", "fields": {"codename": "change_studentmodule", "name": "Can change student module", "content_type": 26}}, {"pk": 78, "model": "auth.permission", "fields": {"codename": "delete_studentmodule", "name": "Can delete student module", "content_type": 26}}, {"pk": 79, "model": "auth.permission", "fields": {"codename": "add_studentmodulehistory", "name": "Can add student module history", "content_type": 27}}, {"pk": 80, "model": "auth.permission", "fields": {"codename": "change_studentmodulehistory", "name": "Can change student module history", "content_type": 27}}, {"pk": 81, "model": "auth.permission", "fields": {"codename": "delete_studentmodulehistory", "name": "Can delete student module history", "content_type": 27}}, {"pk": 88, "model": "auth.permission", "fields": {"codename": "add_xmodulestudentinfofield", "name": "Can add x module student info field", "content_type": 30}}, {"pk": 89, "model": "auth.permission", "fields": {"codename": "change_xmodulestudentinfofield", "name": "Can change x module student info field", "content_type": 30}}, {"pk": 90, "model": "auth.permission", "fields": {"codename": "delete_xmodulestudentinfofield", "name": "Can delete x module student info field", "content_type": 30}}, {"pk": 85, "model": "auth.permission", "fields": {"codename": "add_xmodulestudentprefsfield", "name": "Can add x module student prefs field", "content_type": 29}}, {"pk": 86, "model": "auth.permission", "fields": {"codename": "change_xmodulestudentprefsfield", "name": "Can change x module student prefs field", "content_type": 29}}, {"pk": 87, "model": "auth.permission", "fields": {"codename": "delete_xmodulestudentprefsfield", "name": "Can delete x module student prefs field", "content_type": 29}}, {"pk": 82, "model": "auth.permission", "fields": {"codename": "add_xmoduleuserstatesummaryfield", "name": "Can add x module user state summary field", "content_type": 28}}, {"pk": 83, "model": "auth.permission", "fields": {"codename": "change_xmoduleuserstatesummaryfield", "name": "Can change x module user state summary field", "content_type": 28}}, {"pk": 84, "model": "auth.permission", "fields": {"codename": "delete_xmoduleuserstatesummaryfield", "name": "Can delete x module user state summary field", "content_type": 28}}, {"pk": 325, "model": "auth.permission", "fields": {"codename": "add_coursererunstate", "name": "Can add course rerun state", "content_type": 108}}, {"pk": 326, "model": "auth.permission", "fields": {"codename": "change_coursererunstate", "name": "Can change course rerun state", "content_type": 108}}, {"pk": 327, "model": "auth.permission", "fields": {"codename": "delete_coursererunstate", "name": "Can delete course rerun state", "content_type": 108}}, {"pk": 442, "model": "auth.permission", "fields": {"codename": "add_coursecreator", "name": "Can add course creator", "content_type": 147}}, {"pk": 443, "model": "auth.permission", "fields": {"codename": "change_coursecreator", "name": "Can change course creator", "content_type": 147}}, {"pk": 444, "model": "auth.permission", "fields": {"codename": "delete_coursecreator", "name": "Can delete course creator", "content_type": 147}}, {"pk": 157, "model": "auth.permission", "fields": {"codename": "add_courseusergroup", "name": "Can add course user group", "content_type": 53}}, {"pk": 158, "model": "auth.permission", "fields": {"codename": "change_courseusergroup", "name": "Can change course user group", "content_type": 53}}, {"pk": 159, "model": "auth.permission", "fields": {"codename": "delete_courseusergroup", "name": "Can delete course user group", "content_type": 53}}, {"pk": 160, "model": "auth.permission", "fields": {"codename": "add_courseusergrouppartitiongroup", "name": "Can add course user group partition group", "content_type": 54}}, {"pk": 161, "model": "auth.permission", "fields": {"codename": "change_courseusergrouppartitiongroup", "name": "Can change course user group partition group", "content_type": 54}}, {"pk": 162, "model": "auth.permission", "fields": {"codename": "delete_courseusergrouppartitiongroup", "name": "Can delete course user group partition group", "content_type": 54}}, {"pk": 301, "model": "auth.permission", "fields": {"codename": "add_coursemode", "name": "Can add course mode", "content_type": 100}}, {"pk": 302, "model": "auth.permission", "fields": {"codename": "change_coursemode", "name": "Can change course mode", "content_type": 100}}, {"pk": 303, "model": "auth.permission", "fields": {"codename": "delete_coursemode", "name": "Can delete course mode", "content_type": 100}}, {"pk": 304, "model": "auth.permission", "fields": {"codename": "add_coursemodesarchive", "name": "Can add course modes archive", "content_type": 101}}, {"pk": 305, "model": "auth.permission", "fields": {"codename": "change_coursemodesarchive", "name": "Can change course modes archive", "content_type": 101}}, {"pk": 306, "model": "auth.permission", "fields": {"codename": "delete_coursemodesarchive", "name": "Can delete course modes archive", "content_type": 101}}, {"pk": 310, "model": "auth.permission", "fields": {"codename": "add_darklangconfig", "name": "Can add dark lang config", "content_type": 103}}, {"pk": 311, "model": "auth.permission", "fields": {"codename": "change_darklangconfig", "name": "Can change dark lang config", "content_type": 103}}, {"pk": 312, "model": "auth.permission", "fields": {"codename": "delete_darklangconfig", "name": "Can delete dark lang config", "content_type": 103}}, {"pk": 70, "model": "auth.permission", "fields": {"codename": "add_association", "name": "Can add association", "content_type": 24}}, {"pk": 71, "model": "auth.permission", "fields": {"codename": "change_association", "name": "Can change association", "content_type": 24}}, {"pk": 72, "model": "auth.permission", "fields": {"codename": "delete_association", "name": "Can delete association", "content_type": 24}}, {"pk": 73, "model": "auth.permission", "fields": {"codename": "add_code", "name": "Can add code", "content_type": 25}}, {"pk": 74, "model": "auth.permission", "fields": {"codename": "change_code", "name": "Can change code", "content_type": 25}}, {"pk": 75, "model": "auth.permission", "fields": {"codename": "delete_code", "name": "Can delete code", "content_type": 25}}, {"pk": 67, "model": "auth.permission", "fields": {"codename": "add_nonce", "name": "Can add nonce", "content_type": 23}}, {"pk": 68, "model": "auth.permission", "fields": {"codename": "change_nonce", "name": "Can change nonce", "content_type": 23}}, {"pk": 69, "model": "auth.permission", "fields": {"codename": "delete_nonce", "name": "Can delete nonce", "content_type": 23}}, {"pk": 64, "model": "auth.permission", "fields": {"codename": "add_usersocialauth", "name": "Can add user social auth", "content_type": 22}}, {"pk": 65, "model": "auth.permission", "fields": {"codename": "change_usersocialauth", "name": "Can change user social auth", "content_type": 22}}, {"pk": 66, "model": "auth.permission", "fields": {"codename": "delete_usersocialauth", "name": "Can delete user social auth", "content_type": 22}}, {"pk": 235, "model": "auth.permission", "fields": {"codename": "add_notification", "name": "Can add notification", "content_type": 78}}, {"pk": 236, "model": "auth.permission", "fields": {"codename": "change_notification", "name": "Can change notification", "content_type": 78}}, {"pk": 237, "model": "auth.permission", "fields": {"codename": "delete_notification", "name": "Can delete notification", "content_type": 78}}, {"pk": 226, "model": "auth.permission", "fields": {"codename": "add_notificationtype", "name": "Can add type", "content_type": 75}}, {"pk": 227, "model": "auth.permission", "fields": {"codename": "change_notificationtype", "name": "Can change type", "content_type": 75}}, {"pk": 228, "model": "auth.permission", "fields": {"codename": "delete_notificationtype", "name": "Can delete type", "content_type": 75}}, {"pk": 229, "model": "auth.permission", "fields": {"codename": "add_settings", "name": "Can add settings", "content_type": 76}}, {"pk": 230, "model": "auth.permission", "fields": {"codename": "change_settings", "name": "Can change settings", "content_type": 76}}, {"pk": 231, "model": "auth.permission", "fields": {"codename": "delete_settings", "name": "Can delete settings", "content_type": 76}}, {"pk": 232, "model": "auth.permission", "fields": {"codename": "add_subscription", "name": "Can add subscription", "content_type": 77}}, {"pk": 233, "model": "auth.permission", "fields": {"codename": "change_subscription", "name": "Can change subscription", "content_type": 77}}, {"pk": 234, "model": "auth.permission", "fields": {"codename": "delete_subscription", "name": "Can delete subscription", "content_type": 77}}, {"pk": 55, "model": "auth.permission", "fields": {"codename": "add_association", "name": "Can add association", "content_type": 19}}, {"pk": 56, "model": "auth.permission", "fields": {"codename": "change_association", "name": "Can change association", "content_type": 19}}, {"pk": 57, "model": "auth.permission", "fields": {"codename": "delete_association", "name": "Can delete association", "content_type": 19}}, {"pk": 52, "model": "auth.permission", "fields": {"codename": "add_nonce", "name": "Can add nonce", "content_type": 18}}, {"pk": 53, "model": "auth.permission", "fields": {"codename": "change_nonce", "name": "Can change nonce", "content_type": 18}}, {"pk": 54, "model": "auth.permission", "fields": {"codename": "delete_nonce", "name": "Can delete nonce", "content_type": 18}}, {"pk": 58, "model": "auth.permission", "fields": {"codename": "add_useropenid", "name": "Can add user open id", "content_type": 20}}, {"pk": 59, "model": "auth.permission", "fields": {"codename": "change_useropenid", "name": "Can change user open id", "content_type": 20}}, {"pk": 60, "model": "auth.permission", "fields": {"codename": "delete_useropenid", "name": "Can delete user open id", "content_type": 20}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_crontabschedule", "name": "Can add crontab", "content_type": 10}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_crontabschedule", "name": "Can change crontab", "content_type": 10}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_crontabschedule", "name": "Can delete crontab", "content_type": 10}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_intervalschedule", "name": "Can add interval", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_intervalschedule", "name": "Can change interval", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_intervalschedule", "name": "Can delete interval", "content_type": 9}}, {"pk": 34, "model": "auth.permission", "fields": {"codename": "add_periodictask", "name": "Can add periodic task", "content_type": 12}}, {"pk": 35, "model": "auth.permission", "fields": {"codename": "change_periodictask", "name": "Can change periodic task", "content_type": 12}}, {"pk": 36, "model": "auth.permission", "fields": {"codename": "delete_periodictask", "name": "Can delete periodic task", "content_type": 12}}, {"pk": 31, "model": "auth.permission", "fields": {"codename": "add_periodictasks", "name": "Can add periodic tasks", "content_type": 11}}, {"pk": 32, "model": "auth.permission", "fields": {"codename": "change_periodictasks", "name": "Can change periodic tasks", "content_type": 11}}, {"pk": 33, "model": "auth.permission", "fields": {"codename": "delete_periodictasks", "name": "Can delete periodic tasks", "content_type": 11}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_taskmeta", "name": "Can add task state", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_taskmeta", "name": "Can change task state", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_taskmeta", "name": "Can delete task state", "content_type": 7}}, {"pk": 22, "model": "auth.permission", "fields": {"codename": "add_tasksetmeta", "name": "Can add saved group result", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_tasksetmeta", "name": "Can change saved group result", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_tasksetmeta", "name": "Can delete saved group result", "content_type": 8}}, {"pk": 40, "model": "auth.permission", "fields": {"codename": "add_taskstate", "name": "Can add task", "content_type": 14}}, {"pk": 41, "model": "auth.permission", "fields": {"codename": "change_taskstate", "name": "Can change task", "content_type": 14}}, {"pk": 42, "model": "auth.permission", "fields": {"codename": "delete_taskstate", "name": "Can delete task", "content_type": 14}}, {"pk": 37, "model": "auth.permission", "fields": {"codename": "add_workerstate", "name": "Can add worker", "content_type": 13}}, {"pk": 38, "model": "auth.permission", "fields": {"codename": "change_workerstate", "name": "Can change worker", "content_type": 13}}, {"pk": 39, "model": "auth.permission", "fields": {"codename": "delete_workerstate", "name": "Can delete worker", "content_type": 13}}, {"pk": 415, "model": "auth.permission", "fields": {"codename": "add_coursevideo", "name": "Can add course video", "content_type": 138}}, {"pk": 416, "model": "auth.permission", "fields": {"codename": "change_coursevideo", "name": "Can change course video", "content_type": 138}}, {"pk": 417, "model": "auth.permission", "fields": {"codename": "delete_coursevideo", "name": "Can delete course video", "content_type": 138}}, {"pk": 418, "model": "auth.permission", "fields": {"codename": "add_encodedvideo", "name": "Can add encoded video", "content_type": 139}}, {"pk": 419, "model": "auth.permission", "fields": {"codename": "change_encodedvideo", "name": "Can change encoded video", "content_type": 139}}, {"pk": 420, "model": "auth.permission", "fields": {"codename": "delete_encodedvideo", "name": "Can delete encoded video", "content_type": 139}}, {"pk": 409, "model": "auth.permission", "fields": {"codename": "add_profile", "name": "Can add profile", "content_type": 136}}, {"pk": 410, "model": "auth.permission", "fields": {"codename": "change_profile", "name": "Can change profile", "content_type": 136}}, {"pk": 411, "model": "auth.permission", "fields": {"codename": "delete_profile", "name": "Can delete profile", "content_type": 136}}, {"pk": 421, "model": "auth.permission", "fields": {"codename": "add_subtitle", "name": "Can add subtitle", "content_type": 140}}, {"pk": 422, "model": "auth.permission", "fields": {"codename": "change_subtitle", "name": "Can change subtitle", "content_type": 140}}, {"pk": 423, "model": "auth.permission", "fields": {"codename": "delete_subtitle", "name": "Can delete subtitle", "content_type": 140}}, {"pk": 412, "model": "auth.permission", "fields": {"codename": "add_video", "name": "Can add video", "content_type": 137}}, {"pk": 413, "model": "auth.permission", "fields": {"codename": "change_video", "name": "Can change video", "content_type": 137}}, {"pk": 414, "model": "auth.permission", "fields": {"codename": "delete_video", "name": "Can delete video", "content_type": 137}}, {"pk": 316, "model": "auth.permission", "fields": {"codename": "add_embargoedcourse", "name": "Can add embargoed course", "content_type": 105}}, {"pk": 317, "model": "auth.permission", "fields": {"codename": "change_embargoedcourse", "name": "Can change embargoed course", "content_type": 105}}, {"pk": 318, "model": "auth.permission", "fields": {"codename": "delete_embargoedcourse", "name": "Can delete embargoed course", "content_type": 105}}, {"pk": 319, "model": "auth.permission", "fields": {"codename": "add_embargoedstate", "name": "Can add embargoed state", "content_type": 106}}, {"pk": 320, "model": "auth.permission", "fields": {"codename": "change_embargoedstate", "name": "Can change embargoed state", "content_type": 106}}, {"pk": 321, "model": "auth.permission", "fields": {"codename": "delete_embargoedstate", "name": "Can delete embargoed state", "content_type": 106}}, {"pk": 322, "model": "auth.permission", "fields": {"codename": "add_ipfilter", "name": "Can add ip filter", "content_type": 107}}, {"pk": 323, "model": "auth.permission", "fields": {"codename": "change_ipfilter", "name": "Can change ip filter", "content_type": 107}}, {"pk": 324, "model": "auth.permission", "fields": {"codename": "delete_ipfilter", "name": "Can delete ip filter", "content_type": 107}}, {"pk": 175, "model": "auth.permission", "fields": {"codename": "add_externalauthmap", "name": "Can add external auth map", "content_type": 59}}, {"pk": 176, "model": "auth.permission", "fields": {"codename": "change_externalauthmap", "name": "Can change external auth map", "content_type": 59}}, {"pk": 177, "model": "auth.permission", "fields": {"codename": "delete_externalauthmap", "name": "Can delete external auth map", "content_type": 59}}, {"pk": 241, "model": "auth.permission", "fields": {"codename": "add_puzzlecomplete", "name": "Can add puzzle complete", "content_type": 80}}, {"pk": 242, "model": "auth.permission", "fields": {"codename": "change_puzzlecomplete", "name": "Can change puzzle complete", "content_type": 80}}, {"pk": 243, "model": "auth.permission", "fields": {"codename": "delete_puzzlecomplete", "name": "Can delete puzzle complete", "content_type": 80}}, {"pk": 238, "model": "auth.permission", "fields": {"codename": "add_score", "name": "Can add score", "content_type": 79}}, {"pk": 239, "model": "auth.permission", "fields": {"codename": "change_score", "name": "Can change score", "content_type": 79}}, {"pk": 240, "model": "auth.permission", "fields": {"codename": "delete_score", "name": "Can delete score", "content_type": 79}}, {"pk": 148, "model": "auth.permission", "fields": {"codename": "add_instructortask", "name": "Can add instructor task", "content_type": 50}}, {"pk": 149, "model": "auth.permission", "fields": {"codename": "change_instructortask", "name": "Can change instructor task", "content_type": 50}}, {"pk": 150, "model": "auth.permission", "fields": {"codename": "delete_instructortask", "name": "Can delete instructor task", "content_type": 50}}, {"pk": 151, "model": "auth.permission", "fields": {"codename": "add_coursesoftware", "name": "Can add course software", "content_type": 51}}, {"pk": 152, "model": "auth.permission", "fields": {"codename": "change_coursesoftware", "name": "Can change course software", "content_type": 51}}, {"pk": 153, "model": "auth.permission", "fields": {"codename": "delete_coursesoftware", "name": "Can delete course software", "content_type": 51}}, {"pk": 154, "model": "auth.permission", "fields": {"codename": "add_userlicense", "name": "Can add user license", "content_type": 52}}, {"pk": 155, "model": "auth.permission", "fields": {"codename": "change_userlicense", "name": "Can change user license", "content_type": 52}}, {"pk": 156, "model": "auth.permission", "fields": {"codename": "delete_userlicense", "name": "Can delete user license", "content_type": 52}}, {"pk": 334, "model": "auth.permission", "fields": {"codename": "add_xblockasidesconfig", "name": "Can add x block asides config", "content_type": 111}}, {"pk": 335, "model": "auth.permission", "fields": {"codename": "change_xblockasidesconfig", "name": "Can change x block asides config", "content_type": 111}}, {"pk": 336, "model": "auth.permission", "fields": {"codename": "delete_xblockasidesconfig", "name": "Can delete x block asides config", "content_type": 111}}, {"pk": 337, "model": "auth.permission", "fields": {"codename": "add_answer", "name": "Can add answer", "content_type": 112}}, {"pk": 338, "model": "auth.permission", "fields": {"codename": "change_answer", "name": "Can change answer", "content_type": 112}}, {"pk": 339, "model": "auth.permission", "fields": {"codename": "delete_answer", "name": "Can delete answer", "content_type": 112}}, {"pk": 340, "model": "auth.permission", "fields": {"codename": "add_lightchild", "name": "Can add light child", "content_type": 113}}, {"pk": 341, "model": "auth.permission", "fields": {"codename": "change_lightchild", "name": "Can change light child", "content_type": 113}}, {"pk": 342, "model": "auth.permission", "fields": {"codename": "delete_lightchild", "name": "Can delete light child", "content_type": 113}}, {"pk": 433, "model": "auth.permission", "fields": {"codename": "add_coursecontentmilestone", "name": "Can add course content milestone", "content_type": 144}}, {"pk": 434, "model": "auth.permission", "fields": {"codename": "change_coursecontentmilestone", "name": "Can change course content milestone", "content_type": 144}}, {"pk": 435, "model": "auth.permission", "fields": {"codename": "delete_coursecontentmilestone", "name": "Can delete course content milestone", "content_type": 144}}, {"pk": 430, "model": "auth.permission", "fields": {"codename": "add_coursemilestone", "name": "Can add course milestone", "content_type": 143}}, {"pk": 431, "model": "auth.permission", "fields": {"codename": "change_coursemilestone", "name": "Can change course milestone", "content_type": 143}}, {"pk": 432, "model": "auth.permission", "fields": {"codename": "delete_coursemilestone", "name": "Can delete course milestone", "content_type": 143}}, {"pk": 424, "model": "auth.permission", "fields": {"codename": "add_milestone", "name": "Can add milestone", "content_type": 141}}, {"pk": 425, "model": "auth.permission", "fields": {"codename": "change_milestone", "name": "Can change milestone", "content_type": 141}}, {"pk": 426, "model": "auth.permission", "fields": {"codename": "delete_milestone", "name": "Can delete milestone", "content_type": 141}}, {"pk": 427, "model": "auth.permission", "fields": {"codename": "add_milestonerelationshiptype", "name": "Can add milestone relationship type", "content_type": 142}}, {"pk": 428, "model": "auth.permission", "fields": {"codename": "change_milestonerelationshiptype", "name": "Can change milestone relationship type", "content_type": 142}}, {"pk": 429, "model": "auth.permission", "fields": {"codename": "delete_milestonerelationshiptype", "name": "Can delete milestone relationship type", "content_type": 142}}, {"pk": 436, "model": "auth.permission", "fields": {"codename": "add_usermilestone", "name": "Can add user milestone", "content_type": 145}}, {"pk": 437, "model": "auth.permission", "fields": {"codename": "change_usermilestone", "name": "Can change user milestone", "content_type": 145}}, {"pk": 438, "model": "auth.permission", "fields": {"codename": "delete_usermilestone", "name": "Can delete user milestone", "content_type": 145}}, {"pk": 244, "model": "auth.permission", "fields": {"codename": "add_note", "name": "Can add note", "content_type": 81}}, {"pk": 245, "model": "auth.permission", "fields": {"codename": "change_note", "name": "Can change note", "content_type": 81}}, {"pk": 246, "model": "auth.permission", "fields": {"codename": "delete_note", "name": "Can delete note", "content_type": 81}}, {"pk": 184, "model": "auth.permission", "fields": {"codename": "add_accesstoken", "name": "Can add access token", "content_type": 62}}, {"pk": 185, "model": "auth.permission", "fields": {"codename": "change_accesstoken", "name": "Can change access token", "content_type": 62}}, {"pk": 186, "model": "auth.permission", "fields": {"codename": "delete_accesstoken", "name": "Can delete access token", "content_type": 62}}, {"pk": 178, "model": "auth.permission", "fields": {"codename": "add_client", "name": "Can add client", "content_type": 60}}, {"pk": 179, "model": "auth.permission", "fields": {"codename": "change_client", "name": "Can change client", "content_type": 60}}, {"pk": 180, "model": "auth.permission", "fields": {"codename": "delete_client", "name": "Can delete client", "content_type": 60}}, {"pk": 181, "model": "auth.permission", "fields": {"codename": "add_grant", "name": "Can add grant", "content_type": 61}}, {"pk": 182, "model": "auth.permission", "fields": {"codename": "change_grant", "name": "Can change grant", "content_type": 61}}, {"pk": 183, "model": "auth.permission", "fields": {"codename": "delete_grant", "name": "Can delete grant", "content_type": 61}}, {"pk": 187, "model": "auth.permission", "fields": {"codename": "add_refreshtoken", "name": "Can add refresh token", "content_type": 63}}, {"pk": 188, "model": "auth.permission", "fields": {"codename": "change_refreshtoken", "name": "Can change refresh token", "content_type": 63}}, {"pk": 189, "model": "auth.permission", "fields": {"codename": "delete_refreshtoken", "name": "Can delete refresh token", "content_type": 63}}, {"pk": 190, "model": "auth.permission", "fields": {"codename": "add_trustedclient", "name": "Can add trusted client", "content_type": 64}}, {"pk": 191, "model": "auth.permission", "fields": {"codename": "change_trustedclient", "name": "Can change trusted client", "content_type": 64}}, {"pk": 192, "model": "auth.permission", "fields": {"codename": "delete_trustedclient", "name": "Can delete trusted client", "content_type": 64}}, {"pk": 49, "model": "auth.permission", "fields": {"codename": "add_psychometricdata", "name": "Can add psychometric data", "content_type": 17}}, {"pk": 50, "model": "auth.permission", "fields": {"codename": "change_psychometricdata", "name": "Can change psychometric data", "content_type": 17}}, {"pk": 51, "model": "auth.permission", "fields": {"codename": "delete_psychometricdata", "name": "Can delete psychometric data", "content_type": 17}}, {"pk": 313, "model": "auth.permission", "fields": {"codename": "add_midcoursereverificationwindow", "name": "Can add midcourse reverification window", "content_type": 104}}, {"pk": 314, "model": "auth.permission", "fields": {"codename": "change_midcoursereverificationwindow", "name": "Can change midcourse reverification window", "content_type": 104}}, {"pk": 315, "model": "auth.permission", "fields": {"codename": "delete_midcoursereverificationwindow", "name": "Can delete midcourse reverification window", "content_type": 104}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 5}}, {"pk": 292, "model": "auth.permission", "fields": {"codename": "add_certificateitem", "name": "Can add certificate item", "content_type": 97}}, {"pk": 293, "model": "auth.permission", "fields": {"codename": "change_certificateitem", "name": "Can change certificate item", "content_type": 97}}, {"pk": 294, "model": "auth.permission", "fields": {"codename": "delete_certificateitem", "name": "Can delete certificate item", "content_type": 97}}, {"pk": 274, "model": "auth.permission", "fields": {"codename": "add_coupon", "name": "Can add coupon", "content_type": 91}}, {"pk": 275, "model": "auth.permission", "fields": {"codename": "change_coupon", "name": "Can change coupon", "content_type": 91}}, {"pk": 276, "model": "auth.permission", "fields": {"codename": "delete_coupon", "name": "Can delete coupon", "content_type": 91}}, {"pk": 277, "model": "auth.permission", "fields": {"codename": "add_couponredemption", "name": "Can add coupon redemption", "content_type": 92}}, {"pk": 278, "model": "auth.permission", "fields": {"codename": "change_couponredemption", "name": "Can change coupon redemption", "content_type": 92}}, {"pk": 279, "model": "auth.permission", "fields": {"codename": "delete_couponredemption", "name": "Can delete coupon redemption", "content_type": 92}}, {"pk": 283, "model": "auth.permission", "fields": {"codename": "add_courseregcodeitem", "name": "Can add course reg code item", "content_type": 94}}, {"pk": 284, "model": "auth.permission", "fields": {"codename": "change_courseregcodeitem", "name": "Can change course reg code item", "content_type": 94}}, {"pk": 285, "model": "auth.permission", "fields": {"codename": "delete_courseregcodeitem", "name": "Can delete course reg code item", "content_type": 94}}, {"pk": 286, "model": "auth.permission", "fields": {"codename": "add_courseregcodeitemannotation", "name": "Can add course reg code item annotation", "content_type": 95}}, {"pk": 287, "model": "auth.permission", "fields": {"codename": "change_courseregcodeitemannotation", "name": "Can change course reg code item annotation", "content_type": 95}}, {"pk": 288, "model": "auth.permission", "fields": {"codename": "delete_courseregcodeitemannotation", "name": "Can delete course reg code item annotation", "content_type": 95}}, {"pk": 268, "model": "auth.permission", "fields": {"codename": "add_courseregistrationcode", "name": "Can add course registration code", "content_type": 89}}, {"pk": 269, "model": "auth.permission", "fields": {"codename": "change_courseregistrationcode", "name": "Can change course registration code", "content_type": 89}}, {"pk": 270, "model": "auth.permission", "fields": {"codename": "delete_courseregistrationcode", "name": "Can delete course registration code", "content_type": 89}}, {"pk": 298, "model": "auth.permission", "fields": {"codename": "add_donation", "name": "Can add donation", "content_type": 99}}, {"pk": 299, "model": "auth.permission", "fields": {"codename": "change_donation", "name": "Can change donation", "content_type": 99}}, {"pk": 300, "model": "auth.permission", "fields": {"codename": "delete_donation", "name": "Can delete donation", "content_type": 99}}, {"pk": 295, "model": "auth.permission", "fields": {"codename": "add_donationconfiguration", "name": "Can add donation configuration", "content_type": 98}}, {"pk": 296, "model": "auth.permission", "fields": {"codename": "change_donationconfiguration", "name": "Can change donation configuration", "content_type": 98}}, {"pk": 297, "model": "auth.permission", "fields": {"codename": "delete_donationconfiguration", "name": "Can delete donation configuration", "content_type": 98}}, {"pk": 265, "model": "auth.permission", "fields": {"codename": "add_invoice", "name": "Can add invoice", "content_type": 88}}, {"pk": 266, "model": "auth.permission", "fields": {"codename": "change_invoice", "name": "Can change invoice", "content_type": 88}}, {"pk": 267, "model": "auth.permission", "fields": {"codename": "delete_invoice", "name": "Can delete invoice", "content_type": 88}}, {"pk": 259, "model": "auth.permission", "fields": {"codename": "add_order", "name": "Can add order", "content_type": 86}}, {"pk": 260, "model": "auth.permission", "fields": {"codename": "change_order", "name": "Can change order", "content_type": 86}}, {"pk": 261, "model": "auth.permission", "fields": {"codename": "delete_order", "name": "Can delete order", "content_type": 86}}, {"pk": 262, "model": "auth.permission", "fields": {"codename": "add_orderitem", "name": "Can add order item", "content_type": 87}}, {"pk": 263, "model": "auth.permission", "fields": {"codename": "change_orderitem", "name": "Can change order item", "content_type": 87}}, {"pk": 264, "model": "auth.permission", "fields": {"codename": "delete_orderitem", "name": "Can delete order item", "content_type": 87}}, {"pk": 280, "model": "auth.permission", "fields": {"codename": "add_paidcourseregistration", "name": "Can add paid course registration", "content_type": 93}}, {"pk": 281, "model": "auth.permission", "fields": {"codename": "change_paidcourseregistration", "name": "Can change paid course registration", "content_type": 93}}, {"pk": 282, "model": "auth.permission", "fields": {"codename": "delete_paidcourseregistration", "name": "Can delete paid course registration", "content_type": 93}}, {"pk": 289, "model": "auth.permission", "fields": {"codename": "add_paidcourseregistrationannotation", "name": "Can add paid course registration annotation", "content_type": 96}}, {"pk": 290, "model": "auth.permission", "fields": {"codename": "change_paidcourseregistrationannotation", "name": "Can change paid course registration annotation", "content_type": 96}}, {"pk": 291, "model": "auth.permission", "fields": {"codename": "delete_paidcourseregistrationannotation", "name": "Can delete paid course registration annotation", "content_type": 96}}, {"pk": 271, "model": "auth.permission", "fields": {"codename": "add_registrationcoderedemption", "name": "Can add registration code redemption", "content_type": 90}}, {"pk": 272, "model": "auth.permission", "fields": {"codename": "change_registrationcoderedemption", "name": "Can change registration code redemption", "content_type": 90}}, {"pk": 273, "model": "auth.permission", "fields": {"codename": "delete_registrationcoderedemption", "name": "Can delete registration code redemption", "content_type": 90}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 6}}, {"pk": 43, "model": "auth.permission", "fields": {"codename": "add_migrationhistory", "name": "Can add migration history", "content_type": 15}}, {"pk": 44, "model": "auth.permission", "fields": {"codename": "change_migrationhistory", "name": "Can change migration history", "content_type": 15}}, {"pk": 45, "model": "auth.permission", "fields": {"codename": "delete_migrationhistory", "name": "Can delete migration history", "content_type": 15}}, {"pk": 247, "model": "auth.permission", "fields": {"codename": "add_splashconfig", "name": "Can add splash config", "content_type": 82}}, {"pk": 248, "model": "auth.permission", "fields": {"codename": "change_splashconfig", "name": "Can change splash config", "content_type": 82}}, {"pk": 249, "model": "auth.permission", "fields": {"codename": "delete_splashconfig", "name": "Can delete splash config", "content_type": 82}}, {"pk": 97, "model": "auth.permission", "fields": {"codename": "add_anonymoususerid", "name": "Can add anonymous user id", "content_type": 33}}, {"pk": 98, "model": "auth.permission", "fields": {"codename": "change_anonymoususerid", "name": "Can change anonymous user id", "content_type": 33}}, {"pk": 99, "model": "auth.permission", "fields": {"codename": "delete_anonymoususerid", "name": "Can delete anonymous user id", "content_type": 33}}, {"pk": 133, "model": "auth.permission", "fields": {"codename": "add_courseaccessrole", "name": "Can add course access role", "content_type": 45}}, {"pk": 134, "model": "auth.permission", "fields": {"codename": "change_courseaccessrole", "name": "Can change course access role", "content_type": 45}}, {"pk": 135, "model": "auth.permission", "fields": {"codename": "delete_courseaccessrole", "name": "Can delete course access role", "content_type": 45}}, {"pk": 127, "model": "auth.permission", "fields": {"codename": "add_courseenrollment", "name": "Can add course enrollment", "content_type": 43}}, {"pk": 128, "model": "auth.permission", "fields": {"codename": "change_courseenrollment", "name": "Can change course enrollment", "content_type": 43}}, {"pk": 129, "model": "auth.permission", "fields": {"codename": "delete_courseenrollment", "name": "Can delete course enrollment", "content_type": 43}}, {"pk": 130, "model": "auth.permission", "fields": {"codename": "add_courseenrollmentallowed", "name": "Can add course enrollment allowed", "content_type": 44}}, {"pk": 131, "model": "auth.permission", "fields": {"codename": "change_courseenrollmentallowed", "name": "Can change course enrollment allowed", "content_type": 44}}, {"pk": 132, "model": "auth.permission", "fields": {"codename": "delete_courseenrollmentallowed", "name": "Can delete course enrollment allowed", "content_type": 44}}, {"pk": 136, "model": "auth.permission", "fields": {"codename": "add_dashboardconfiguration", "name": "Can add dashboard configuration", "content_type": 46}}, {"pk": 137, "model": "auth.permission", "fields": {"codename": "change_dashboardconfiguration", "name": "Can change dashboard configuration", "content_type": 46}}, {"pk": 138, "model": "auth.permission", "fields": {"codename": "delete_dashboardconfiguration", "name": "Can delete dashboard configuration", "content_type": 46}}, {"pk": 124, "model": "auth.permission", "fields": {"codename": "add_loginfailures", "name": "Can add login failures", "content_type": 42}}, {"pk": 125, "model": "auth.permission", "fields": {"codename": "change_loginfailures", "name": "Can change login failures", "content_type": 42}}, {"pk": 126, "model": "auth.permission", "fields": {"codename": "delete_loginfailures", "name": "Can delete login failures", "content_type": 42}}, {"pk": 121, "model": "auth.permission", "fields": {"codename": "add_passwordhistory", "name": "Can add password history", "content_type": 41}}, {"pk": 122, "model": "auth.permission", "fields": {"codename": "change_passwordhistory", "name": "Can change password history", "content_type": 41}}, {"pk": 123, "model": "auth.permission", "fields": {"codename": "delete_passwordhistory", "name": "Can delete password history", "content_type": 41}}, {"pk": 118, "model": "auth.permission", "fields": {"codename": "add_pendingemailchange", "name": "Can add pending email change", "content_type": 40}}, {"pk": 119, "model": "auth.permission", "fields": {"codename": "change_pendingemailchange", "name": "Can change pending email change", "content_type": 40}}, {"pk": 120, "model": "auth.permission", "fields": {"codename": "delete_pendingemailchange", "name": "Can delete pending email change", "content_type": 40}}, {"pk": 115, "model": "auth.permission", "fields": {"codename": "add_pendingnamechange", "name": "Can add pending name change", "content_type": 39}}, {"pk": 116, "model": "auth.permission", "fields": {"codename": "change_pendingnamechange", "name": "Can change pending name change", "content_type": 39}}, {"pk": 117, "model": "auth.permission", "fields": {"codename": "delete_pendingnamechange", "name": "Can delete pending name change", "content_type": 39}}, {"pk": 112, "model": "auth.permission", "fields": {"codename": "add_registration", "name": "Can add registration", "content_type": 38}}, {"pk": 113, "model": "auth.permission", "fields": {"codename": "change_registration", "name": "Can change registration", "content_type": 38}}, {"pk": 114, "model": "auth.permission", "fields": {"codename": "delete_registration", "name": "Can delete registration", "content_type": 38}}, {"pk": 103, "model": "auth.permission", "fields": {"codename": "add_userprofile", "name": "Can add user profile", "content_type": 35}}, {"pk": 104, "model": "auth.permission", "fields": {"codename": "change_userprofile", "name": "Can change user profile", "content_type": 35}}, {"pk": 105, "model": "auth.permission", "fields": {"codename": "delete_userprofile", "name": "Can delete user profile", "content_type": 35}}, {"pk": 106, "model": "auth.permission", "fields": {"codename": "add_usersignupsource", "name": "Can add user signup source", "content_type": 36}}, {"pk": 107, "model": "auth.permission", "fields": {"codename": "change_usersignupsource", "name": "Can change user signup source", "content_type": 36}}, {"pk": 108, "model": "auth.permission", "fields": {"codename": "delete_usersignupsource", "name": "Can delete user signup source", "content_type": 36}}, {"pk": 100, "model": "auth.permission", "fields": {"codename": "add_userstanding", "name": "Can add user standing", "content_type": 34}}, {"pk": 101, "model": "auth.permission", "fields": {"codename": "change_userstanding", "name": "Can change user standing", "content_type": 34}}, {"pk": 102, "model": "auth.permission", "fields": {"codename": "delete_userstanding", "name": "Can delete user standing", "content_type": 34}}, {"pk": 109, "model": "auth.permission", "fields": {"codename": "add_usertestgroup", "name": "Can add user test group", "content_type": 37}}, {"pk": 110, "model": "auth.permission", "fields": {"codename": "change_usertestgroup", "name": "Can change user test group", "content_type": 37}}, {"pk": 111, "model": "auth.permission", "fields": {"codename": "delete_usertestgroup", "name": "Can delete user test group", "content_type": 37}}, {"pk": 349, "model": "auth.permission", "fields": {"codename": "add_score", "name": "Can add score", "content_type": 116}}, {"pk": 350, "model": "auth.permission", "fields": {"codename": "change_score", "name": "Can change score", "content_type": 116}}, {"pk": 351, "model": "auth.permission", "fields": {"codename": "delete_score", "name": "Can delete score", "content_type": 116}}, {"pk": 352, "model": "auth.permission", "fields": {"codename": "add_scoresummary", "name": "Can add score summary", "content_type": 117}}, {"pk": 353, "model": "auth.permission", "fields": {"codename": "change_scoresummary", "name": "Can change score summary", "content_type": 117}}, {"pk": 354, "model": "auth.permission", "fields": {"codename": "delete_scoresummary", "name": "Can delete score summary", "content_type": 117}}, {"pk": 343, "model": "auth.permission", "fields": {"codename": "add_studentitem", "name": "Can add student item", "content_type": 114}}, {"pk": 344, "model": "auth.permission", "fields": {"codename": "change_studentitem", "name": "Can change student item", "content_type": 114}}, {"pk": 345, "model": "auth.permission", "fields": {"codename": "delete_studentitem", "name": "Can delete student item", "content_type": 114}}, {"pk": 346, "model": "auth.permission", "fields": {"codename": "add_submission", "name": "Can add submission", "content_type": 115}}, {"pk": 347, "model": "auth.permission", "fields": {"codename": "change_submission", "name": "Can change submission", "content_type": 115}}, {"pk": 348, "model": "auth.permission", "fields": {"codename": "delete_submission", "name": "Can delete submission", "content_type": 115}}, {"pk": 331, "model": "auth.permission", "fields": {"codename": "add_surveyanswer", "name": "Can add survey answer", "content_type": 110}}, {"pk": 332, "model": "auth.permission", "fields": {"codename": "change_surveyanswer", "name": "Can change survey answer", "content_type": 110}}, {"pk": 333, "model": "auth.permission", "fields": {"codename": "delete_surveyanswer", "name": "Can delete survey answer", "content_type": 110}}, {"pk": 328, "model": "auth.permission", "fields": {"codename": "add_surveyform", "name": "Can add survey form", "content_type": 109}}, {"pk": 329, "model": "auth.permission", "fields": {"codename": "change_surveyform", "name": "Can change survey form", "content_type": 109}}, {"pk": 330, "model": "auth.permission", "fields": {"codename": "delete_surveyform", "name": "Can delete survey form", "content_type": 109}}, {"pk": 139, "model": "auth.permission", "fields": {"codename": "add_trackinglog", "name": "Can add tracking log", "content_type": 47}}, {"pk": 140, "model": "auth.permission", "fields": {"codename": "change_trackinglog", "name": "Can change tracking log", "content_type": 47}}, {"pk": 141, "model": "auth.permission", "fields": {"codename": "delete_trackinglog", "name": "Can delete tracking log", "content_type": 47}}, {"pk": 253, "model": "auth.permission", "fields": {"codename": "add_usercoursetag", "name": "Can add user course tag", "content_type": 84}}, {"pk": 254, "model": "auth.permission", "fields": {"codename": "change_usercoursetag", "name": "Can change user course tag", "content_type": 84}}, {"pk": 255, "model": "auth.permission", "fields": {"codename": "delete_usercoursetag", "name": "Can delete user course tag", "content_type": 84}}, {"pk": 256, "model": "auth.permission", "fields": {"codename": "add_userorgtag", "name": "Can add user org tag", "content_type": 85}}, {"pk": 257, "model": "auth.permission", "fields": {"codename": "change_userorgtag", "name": "Can change user org tag", "content_type": 85}}, {"pk": 258, "model": "auth.permission", "fields": {"codename": "delete_userorgtag", "name": "Can delete user org tag", "content_type": 85}}, {"pk": 250, "model": "auth.permission", "fields": {"codename": "add_userpreference", "name": "Can add user preference", "content_type": 83}}, {"pk": 251, "model": "auth.permission", "fields": {"codename": "change_userpreference", "name": "Can change user preference", "content_type": 83}}, {"pk": 252, "model": "auth.permission", "fields": {"codename": "delete_userpreference", "name": "Can delete user preference", "content_type": 83}}, {"pk": 307, "model": "auth.permission", "fields": {"codename": "add_softwaresecurephotoverification", "name": "Can add software secure photo verification", "content_type": 102}}, {"pk": 308, "model": "auth.permission", "fields": {"codename": "change_softwaresecurephotoverification", "name": "Can change software secure photo verification", "content_type": 102}}, {"pk": 309, "model": "auth.permission", "fields": {"codename": "delete_softwaresecurephotoverification", "name": "Can delete software secure photo verification", "content_type": 102}}, {"pk": 193, "model": "auth.permission", "fields": {"codename": "add_article", "name": "Can add article", "content_type": 65}}, {"pk": 197, "model": "auth.permission", "fields": {"codename": "assign", "name": "Can change ownership of any article", "content_type": 65}}, {"pk": 194, "model": "auth.permission", "fields": {"codename": "change_article", "name": "Can change article", "content_type": 65}}, {"pk": 195, "model": "auth.permission", "fields": {"codename": "delete_article", "name": "Can delete article", "content_type": 65}}, {"pk": 198, "model": "auth.permission", "fields": {"codename": "grant", "name": "Can assign permissions to other users", "content_type": 65}}, {"pk": 196, "model": "auth.permission", "fields": {"codename": "moderate", "name": "Can edit all articles and lock/unlock/restore", "content_type": 65}}, {"pk": 199, "model": "auth.permission", "fields": {"codename": "add_articleforobject", "name": "Can add Article for object", "content_type": 66}}, {"pk": 200, "model": "auth.permission", "fields": {"codename": "change_articleforobject", "name": "Can change Article for object", "content_type": 66}}, {"pk": 201, "model": "auth.permission", "fields": {"codename": "delete_articleforobject", "name": "Can delete Article for object", "content_type": 66}}, {"pk": 208, "model": "auth.permission", "fields": {"codename": "add_articleplugin", "name": "Can add article plugin", "content_type": 69}}, {"pk": 209, "model": "auth.permission", "fields": {"codename": "change_articleplugin", "name": "Can change article plugin", "content_type": 69}}, {"pk": 210, "model": "auth.permission", "fields": {"codename": "delete_articleplugin", "name": "Can delete article plugin", "content_type": 69}}, {"pk": 202, "model": "auth.permission", "fields": {"codename": "add_articlerevision", "name": "Can add article revision", "content_type": 67}}, {"pk": 203, "model": "auth.permission", "fields": {"codename": "change_articlerevision", "name": "Can change article revision", "content_type": 67}}, {"pk": 204, "model": "auth.permission", "fields": {"codename": "delete_articlerevision", "name": "Can delete article revision", "content_type": 67}}, {"pk": 223, "model": "auth.permission", "fields": {"codename": "add_articlesubscription", "name": "Can add article subscription", "content_type": 74}}, {"pk": 224, "model": "auth.permission", "fields": {"codename": "change_articlesubscription", "name": "Can change article subscription", "content_type": 74}}, {"pk": 225, "model": "auth.permission", "fields": {"codename": "delete_articlesubscription", "name": "Can delete article subscription", "content_type": 74}}, {"pk": 211, "model": "auth.permission", "fields": {"codename": "add_reusableplugin", "name": "Can add reusable plugin", "content_type": 70}}, {"pk": 212, "model": "auth.permission", "fields": {"codename": "change_reusableplugin", "name": "Can change reusable plugin", "content_type": 70}}, {"pk": 213, "model": "auth.permission", "fields": {"codename": "delete_reusableplugin", "name": "Can delete reusable plugin", "content_type": 70}}, {"pk": 217, "model": "auth.permission", "fields": {"codename": "add_revisionplugin", "name": "Can add revision plugin", "content_type": 72}}, {"pk": 218, "model": "auth.permission", "fields": {"codename": "change_revisionplugin", "name": "Can change revision plugin", "content_type": 72}}, {"pk": 219, "model": "auth.permission", "fields": {"codename": "delete_revisionplugin", "name": "Can delete revision plugin", "content_type": 72}}, {"pk": 220, "model": "auth.permission", "fields": {"codename": "add_revisionpluginrevision", "name": "Can add revision plugin revision", "content_type": 73}}, {"pk": 221, "model": "auth.permission", "fields": {"codename": "change_revisionpluginrevision", "name": "Can change revision plugin revision", "content_type": 73}}, {"pk": 222, "model": "auth.permission", "fields": {"codename": "delete_revisionpluginrevision", "name": "Can delete revision plugin revision", "content_type": 73}}, {"pk": 214, "model": "auth.permission", "fields": {"codename": "add_simpleplugin", "name": "Can add simple plugin", "content_type": 71}}, {"pk": 215, "model": "auth.permission", "fields": {"codename": "change_simpleplugin", "name": "Can change simple plugin", "content_type": 71}}, {"pk": 216, "model": "auth.permission", "fields": {"codename": "delete_simpleplugin", "name": "Can delete simple plugin", "content_type": 71}}, {"pk": 205, "model": "auth.permission", "fields": {"codename": "add_urlpath", "name": "Can add URL path", "content_type": 68}}, {"pk": 206, "model": "auth.permission", "fields": {"codename": "change_urlpath", "name": "Can change URL path", "content_type": 68}}, {"pk": 207, "model": "auth.permission", "fields": {"codename": "delete_urlpath", "name": "Can delete URL path", "content_type": 68}}, {"pk": 403, "model": "auth.permission", "fields": {"codename": "add_assessmentworkflow", "name": "Can add assessment workflow", "content_type": 134}}, {"pk": 404, "model": "auth.permission", "fields": {"codename": "change_assessmentworkflow", "name": "Can change assessment workflow", "content_type": 134}}, {"pk": 405, "model": "auth.permission", "fields": {"codename": "delete_assessmentworkflow", "name": "Can delete assessment workflow", "content_type": 134}}, {"pk": 406, "model": "auth.permission", "fields": {"codename": "add_assessmentworkflowstep", "name": "Can add assessment workflow step", "content_type": 135}}, {"pk": 407, "model": "auth.permission", "fields": {"codename": "change_assessmentworkflowstep", "name": "Can change assessment workflow step", "content_type": 135}}, {"pk": 408, "model": "auth.permission", "fields": {"codename": "delete_assessmentworkflowstep", "name": "Can delete assessment workflow step", "content_type": 135}}, {"pk": 445, "model": "auth.permission", "fields": {"codename": "add_studioconfig", "name": "Can add studio config", "content_type": 148}}, {"pk": 446, "model": "auth.permission", "fields": {"codename": "change_studioconfig", "name": "Can change studio config", "content_type": 148}}, {"pk": 447, "model": "auth.permission", "fields": {"codename": "delete_studioconfig", "name": "Can delete studio config", "content_type": 148}}, {"pk": 1, "model": "dark_lang.darklangconfig", "fields": {"change_date": "2015-01-15T03:15:35Z", "changed_by": null, "enabled": true, "released_languages": ""}}]
\ No newline at end of file
+[{"pk": 62, "model": "contenttypes.contenttype", "fields": {"model": "accesstoken", "name": "access token", "app_label": "oauth2"}}, {"pk": 131, "model": "contenttypes.contenttype", "fields": {"model": "aiclassifier", "name": "ai classifier", "app_label": "assessment"}}, {"pk": 130, "model": "contenttypes.contenttype", "fields": {"model": "aiclassifierset", "name": "ai classifier set", "app_label": "assessment"}}, {"pk": 133, "model": "contenttypes.contenttype", "fields": {"model": "aigradingworkflow", "name": "ai grading workflow", "app_label": "assessment"}}, {"pk": 132, "model": "contenttypes.contenttype", "fields": {"model": "aitrainingworkflow", "name": "ai training workflow", "app_label": "assessment"}}, {"pk": 33, "model": "contenttypes.contenttype", "fields": {"model": "anonymoususerid", "name": "anonymous user id", "app_label": "student"}}, {"pk": 112, "model": "contenttypes.contenttype", "fields": {"model": "answer", "name": "answer", "app_label": "mentoring"}}, {"pk": 65, "model": "contenttypes.contenttype", "fields": {"model": "article", "name": "article", "app_label": "wiki"}}, {"pk": 66, "model": "contenttypes.contenttype", "fields": {"model": "articleforobject", "name": "Article for object", "app_label": "wiki"}}, {"pk": 69, "model": "contenttypes.contenttype", "fields": {"model": "articleplugin", "name": "article plugin", "app_label": "wiki"}}, {"pk": 67, "model": "contenttypes.contenttype", "fields": {"model": "articlerevision", "name": "article revision", "app_label": "wiki"}}, {"pk": 74, "model": "contenttypes.contenttype", "fields": {"model": "articlesubscription", "name": "article subscription", "app_label": "wiki"}}, {"pk": 121, "model": "contenttypes.contenttype", "fields": {"model": "assessment", "name": "assessment", "app_label": "assessment"}}, {"pk": 124, "model": "contenttypes.contenttype", "fields": {"model": "assessmentfeedback", "name": "assessment feedback", "app_label": "assessment"}}, {"pk": 123, "model": "contenttypes.contenttype", "fields": {"model": "assessmentfeedbackoption", "name": "assessment feedback option", "app_label": "assessment"}}, {"pk": 122, "model": "contenttypes.contenttype", "fields": {"model": "assessmentpart", "name": "assessment part", "app_label": "assessment"}}, {"pk": 134, "model": "contenttypes.contenttype", "fields": {"model": "assessmentworkflow", "name": "assessment workflow", "app_label": "workflow"}}, {"pk": 135, "model": "contenttypes.contenttype", "fields": {"model": "assessmentworkflowstep", "name": "assessment workflow step", "app_label": "workflow"}}, {"pk": 19, "model": "contenttypes.contenttype", "fields": {"model": "association", "name": "association", "app_label": "django_openid_auth"}}, {"pk": 24, "model": "contenttypes.contenttype", "fields": {"model": "association", "name": "association", "app_label": "default"}}, {"pk": 97, "model": "contenttypes.contenttype", "fields": {"model": "certificateitem", "name": "certificate item", "app_label": "shoppingcart"}}, {"pk": 48, "model": "contenttypes.contenttype", "fields": {"model": "certificatewhitelist", "name": "certificate whitelist", "app_label": "certificates"}}, {"pk": 60, "model": "contenttypes.contenttype", "fields": {"model": "client", "name": "client", "app_label": "oauth2"}}, {"pk": 25, "model": "contenttypes.contenttype", "fields": {"model": "code", "name": "code", "app_label": "default"}}, {"pk": 4, "model": "contenttypes.contenttype", "fields": {"model": "contenttype", "name": "content type", "app_label": "contenttypes"}}, {"pk": 91, "model": "contenttypes.contenttype", "fields": {"model": "coupon", "name": "coupon", "app_label": "shoppingcart"}}, {"pk": 92, "model": "contenttypes.contenttype", "fields": {"model": "couponredemption", "name": "coupon redemption", "app_label": "shoppingcart"}}, {"pk": 45, "model": "contenttypes.contenttype", "fields": {"model": "courseaccessrole", "name": "course access role", "app_label": "student"}}, {"pk": 58, "model": "contenttypes.contenttype", "fields": {"model": "courseauthorization", "name": "course authorization", "app_label": "bulk_email"}}, {"pk": 144, "model": "contenttypes.contenttype", "fields": {"model": "coursecontentmilestone", "name": "course content milestone", "app_label": "milestones"}}, {"pk": 147, "model": "contenttypes.contenttype", "fields": {"model": "coursecreator", "name": "course creator", "app_label": "course_creators"}}, {"pk": 55, "model": "contenttypes.contenttype", "fields": {"model": "courseemail", "name": "course email", "app_label": "bulk_email"}}, {"pk": 57, "model": "contenttypes.contenttype", "fields": {"model": "courseemailtemplate", "name": "course email template", "app_label": "bulk_email"}}, {"pk": 43, "model": "contenttypes.contenttype", "fields": {"model": "courseenrollment", "name": "course enrollment", "app_label": "student"}}, {"pk": 44, "model": "contenttypes.contenttype", "fields": {"model": "courseenrollmentallowed", "name": "course enrollment allowed", "app_label": "student"}}, {"pk": 143, "model": "contenttypes.contenttype", "fields": {"model": "coursemilestone", "name": "course milestone", "app_label": "milestones"}}, {"pk": 100, "model": "contenttypes.contenttype", "fields": {"model": "coursemode", "name": "course mode", "app_label": "course_modes"}}, {"pk": 101, "model": "contenttypes.contenttype", "fields": {"model": "coursemodesarchive", "name": "course modes archive", "app_label": "course_modes"}}, {"pk": 94, "model": "contenttypes.contenttype", "fields": {"model": "courseregcodeitem", "name": "course reg code item", "app_label": "shoppingcart"}}, {"pk": 95, "model": "contenttypes.contenttype", "fields": {"model": "courseregcodeitemannotation", "name": "course reg code item annotation", "app_label": "shoppingcart"}}, {"pk": 89, "model": "contenttypes.contenttype", "fields": {"model": "courseregistrationcode", "name": "course registration code", "app_label": "shoppingcart"}}, {"pk": 108, "model": "contenttypes.contenttype", "fields": {"model": "coursererunstate", "name": "course rerun state", "app_label": "course_action_state"}}, {"pk": 51, "model": "contenttypes.contenttype", "fields": {"model": "coursesoftware", "name": "course software", "app_label": "licenses"}}, {"pk": 53, "model": "contenttypes.contenttype", "fields": {"model": "courseusergroup", "name": "course user group", "app_label": "course_groups"}}, {"pk": 54, "model": "contenttypes.contenttype", "fields": {"model": "courseusergrouppartitiongroup", "name": "course user group partition group", "app_label": "course_groups"}}, {"pk": 138, "model": "contenttypes.contenttype", "fields": {"model": "coursevideo", "name": "course video", "app_label": "edxval"}}, {"pk": 119, "model": "contenttypes.contenttype", "fields": {"model": "criterion", "name": "criterion", "app_label": "assessment"}}, {"pk": 120, "model": "contenttypes.contenttype", "fields": {"model": "criterionoption", "name": "criterion option", "app_label": "assessment"}}, {"pk": 10, "model": "contenttypes.contenttype", "fields": {"model": "crontabschedule", "name": "crontab", "app_label": "djcelery"}}, {"pk": 103, "model": "contenttypes.contenttype", "fields": {"model": "darklangconfig", "name": "dark lang config", "app_label": "dark_lang"}}, {"pk": 46, "model": "contenttypes.contenttype", "fields": {"model": "dashboardconfiguration", "name": "dashboard configuration", "app_label": "student"}}, {"pk": 99, "model": "contenttypes.contenttype", "fields": {"model": "donation", "name": "donation", "app_label": "shoppingcart"}}, {"pk": 98, "model": "contenttypes.contenttype", "fields": {"model": "donationconfiguration", "name": "donation configuration", "app_label": "shoppingcart"}}, {"pk": 105, "model": "contenttypes.contenttype", "fields": {"model": "embargoedcourse", "name": "embargoed course", "app_label": "embargo"}}, {"pk": 106, "model": "contenttypes.contenttype", "fields": {"model": "embargoedstate", "name": "embargoed state", "app_label": "embargo"}}, {"pk": 139, "model": "contenttypes.contenttype", "fields": {"model": "encodedvideo", "name": "encoded video", "app_label": "edxval"}}, {"pk": 59, "model": "contenttypes.contenttype", "fields": {"model": "externalauthmap", "name": "external auth map", "app_label": "external_auth"}}, {"pk": 49, "model": "contenttypes.contenttype", "fields": {"model": "generatedcertificate", "name": "generated certificate", "app_label": "certificates"}}, {"pk": 61, "model": "contenttypes.contenttype", "fields": {"model": "grant", "name": "grant", "app_label": "oauth2"}}, {"pk": 2, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "auth"}}, {"pk": 50, "model": "contenttypes.contenttype", "fields": {"model": "instructortask", "name": "instructor task", "app_label": "instructor_task"}}, {"pk": 9, "model": "contenttypes.contenttype", "fields": {"model": "intervalschedule", "name": "interval", "app_label": "djcelery"}}, {"pk": 88, "model": "contenttypes.contenttype", "fields": {"model": "invoice", "name": "invoice", "app_label": "shoppingcart"}}, {"pk": 107, "model": "contenttypes.contenttype", "fields": {"model": "ipfilter", "name": "ip filter", "app_label": "embargo"}}, {"pk": 113, "model": "contenttypes.contenttype", "fields": {"model": "lightchild", "name": "light child", "app_label": "mentoring"}}, {"pk": 21, "model": "contenttypes.contenttype", "fields": {"model": "logentry", "name": "log entry", "app_label": "admin"}}, {"pk": 42, "model": "contenttypes.contenttype", "fields": {"model": "loginfailures", "name": "login failures", "app_label": "student"}}, {"pk": 104, "model": "contenttypes.contenttype", "fields": {"model": "midcoursereverificationwindow", "name": "midcourse reverification window", "app_label": "reverification"}}, {"pk": 15, "model": "contenttypes.contenttype", "fields": {"model": "migrationhistory", "name": "migration history", "app_label": "south"}}, {"pk": 141, "model": "contenttypes.contenttype", "fields": {"model": "milestone", "name": "milestone", "app_label": "milestones"}}, {"pk": 142, "model": "contenttypes.contenttype", "fields": {"model": "milestonerelationshiptype", "name": "milestone relationship type", "app_label": "milestones"}}, {"pk": 18, "model": "contenttypes.contenttype", "fields": {"model": "nonce", "name": "nonce", "app_label": "django_openid_auth"}}, {"pk": 23, "model": "contenttypes.contenttype", "fields": {"model": "nonce", "name": "nonce", "app_label": "default"}}, {"pk": 81, "model": "contenttypes.contenttype", "fields": {"model": "note", "name": "note", "app_label": "notes"}}, {"pk": 78, "model": "contenttypes.contenttype", "fields": {"model": "notification", "name": "notification", "app_label": "django_notify"}}, {"pk": 31, "model": "contenttypes.contenttype", "fields": {"model": "offlinecomputedgrade", "name": "offline computed grade", "app_label": "courseware"}}, {"pk": 32, "model": "contenttypes.contenttype", "fields": {"model": "offlinecomputedgradelog", "name": "offline computed grade log", "app_label": "courseware"}}, {"pk": 56, "model": "contenttypes.contenttype", "fields": {"model": "optout", "name": "optout", "app_label": "bulk_email"}}, {"pk": 86, "model": "contenttypes.contenttype", "fields": {"model": "order", "name": "order", "app_label": "shoppingcart"}}, {"pk": 87, "model": "contenttypes.contenttype", "fields": {"model": "orderitem", "name": "order item", "app_label": "shoppingcart"}}, {"pk": 93, "model": "contenttypes.contenttype", "fields": {"model": "paidcourseregistration", "name": "paid course registration", "app_label": "shoppingcart"}}, {"pk": 96, "model": "contenttypes.contenttype", "fields": {"model": "paidcourseregistrationannotation", "name": "paid course registration annotation", "app_label": "shoppingcart"}}, {"pk": 41, "model": "contenttypes.contenttype", "fields": {"model": "passwordhistory", "name": "password history", "app_label": "student"}}, {"pk": 125, "model": "contenttypes.contenttype", "fields": {"model": "peerworkflow", "name": "peer workflow", "app_label": "assessment"}}, {"pk": 126, "model": "contenttypes.contenttype", "fields": {"model": "peerworkflowitem", "name": "peer workflow item", "app_label": "assessment"}}, {"pk": 40, "model": "contenttypes.contenttype", "fields": {"model": "pendingemailchange", "name": "pending email change", "app_label": "student"}}, {"pk": 39, "model": "contenttypes.contenttype", "fields": {"model": "pendingnamechange", "name": "pending name change", "app_label": "student"}}, {"pk": 12, "model": "contenttypes.contenttype", "fields": {"model": "periodictask", "name": "periodic task", "app_label": "djcelery"}}, {"pk": 11, "model": "contenttypes.contenttype", "fields": {"model": "periodictasks", "name": "periodic tasks", "app_label": "djcelery"}}, {"pk": 1, "model": "contenttypes.contenttype", "fields": {"model": "permission", "name": "permission", "app_label": "auth"}}, {"pk": 136, "model": "contenttypes.contenttype", "fields": {"model": "profile", "name": "profile", "app_label": "edxval"}}, {"pk": 17, "model": "contenttypes.contenttype", "fields": {"model": "psychometricdata", "name": "psychometric data", "app_label": "psychometrics"}}, {"pk": 80, "model": "contenttypes.contenttype", "fields": {"model": "puzzlecomplete", "name": "puzzle complete", "app_label": "foldit"}}, {"pk": 63, "model": "contenttypes.contenttype", "fields": {"model": "refreshtoken", "name": "refresh token", "app_label": "oauth2"}}, {"pk": 38, "model": "contenttypes.contenttype", "fields": {"model": "registration", "name": "registration", "app_label": "student"}}, {"pk": 90, "model": "contenttypes.contenttype", "fields": {"model": "registrationcoderedemption", "name": "registration code redemption", "app_label": "shoppingcart"}}, {"pk": 70, "model": "contenttypes.contenttype", "fields": {"model": "reusableplugin", "name": "reusable plugin", "app_label": "wiki"}}, {"pk": 72, "model": "contenttypes.contenttype", "fields": {"model": "revisionplugin", "name": "revision plugin", "app_label": "wiki"}}, {"pk": 73, "model": "contenttypes.contenttype", "fields": {"model": "revisionpluginrevision", "name": "revision plugin revision", "app_label": "wiki"}}, {"pk": 118, "model": "contenttypes.contenttype", "fields": {"model": "rubric", "name": "rubric", "app_label": "assessment"}}, {"pk": 8, "model": "contenttypes.contenttype", "fields": {"model": "tasksetmeta", "name": "saved group result", "app_label": "djcelery"}}, {"pk": 79, "model": "contenttypes.contenttype", "fields": {"model": "score", "name": "score", "app_label": "foldit"}}, {"pk": 116, "model": "contenttypes.contenttype", "fields": {"model": "score", "name": "score", "app_label": "submissions"}}, {"pk": 117, "model": "contenttypes.contenttype", "fields": {"model": "scoresummary", "name": "score summary", "app_label": "submissions"}}, {"pk": 16, "model": "contenttypes.contenttype", "fields": {"model": "servercircuit", "name": "server circuit", "app_label": "circuit"}}, {"pk": 5, "model": "contenttypes.contenttype", "fields": {"model": "session", "name": "session", "app_label": "sessions"}}, {"pk": 76, "model": "contenttypes.contenttype", "fields": {"model": "settings", "name": "settings", "app_label": "django_notify"}}, {"pk": 71, "model": "contenttypes.contenttype", "fields": {"model": "simpleplugin", "name": "simple plugin", "app_label": "wiki"}}, {"pk": 6, "model": "contenttypes.contenttype", "fields": {"model": "site", "name": "site", "app_label": "sites"}}, {"pk": 102, "model": "contenttypes.contenttype", "fields": {"model": "softwaresecurephotoverification", "name": "software secure photo verification", "app_label": "verify_student"}}, {"pk": 82, "model": "contenttypes.contenttype", "fields": {"model": "splashconfig", "name": "splash config", "app_label": "splash"}}, {"pk": 114, "model": "contenttypes.contenttype", "fields": {"model": "studentitem", "name": "student item", "app_label": "submissions"}}, {"pk": 26, "model": "contenttypes.contenttype", "fields": {"model": "studentmodule", "name": "student module", "app_label": "courseware"}}, {"pk": 27, "model": "contenttypes.contenttype", "fields": {"model": "studentmodulehistory", "name": "student module history", "app_label": "courseware"}}, {"pk": 128, "model": "contenttypes.contenttype", "fields": {"model": "studenttrainingworkflow", "name": "student training workflow", "app_label": "assessment"}}, {"pk": 129, "model": "contenttypes.contenttype", "fields": {"model": "studenttrainingworkflowitem", "name": "student training workflow item", "app_label": "assessment"}}, {"pk": 148, "model": "contenttypes.contenttype", "fields": {"model": "studioconfig", "name": "studio config", "app_label": "xblock_config"}}, {"pk": 115, "model": "contenttypes.contenttype", "fields": {"model": "submission", "name": "submission", "app_label": "submissions"}}, {"pk": 77, "model": "contenttypes.contenttype", "fields": {"model": "subscription", "name": "subscription", "app_label": "django_notify"}}, {"pk": 140, "model": "contenttypes.contenttype", "fields": {"model": "subtitle", "name": "subtitle", "app_label": "edxval"}}, {"pk": 110, "model": "contenttypes.contenttype", "fields": {"model": "surveyanswer", "name": "survey answer", "app_label": "survey"}}, {"pk": 109, "model": "contenttypes.contenttype", "fields": {"model": "surveyform", "name": "survey form", "app_label": "survey"}}, {"pk": 14, "model": "contenttypes.contenttype", "fields": {"model": "taskstate", "name": "task", "app_label": "djcelery"}}, {"pk": 7, "model": "contenttypes.contenttype", "fields": {"model": "taskmeta", "name": "task state", "app_label": "djcelery"}}, {"pk": 47, "model": "contenttypes.contenttype", "fields": {"model": "trackinglog", "name": "tracking log", "app_label": "track"}}, {"pk": 127, "model": "contenttypes.contenttype", "fields": {"model": "trainingexample", "name": "training example", "app_label": "assessment"}}, {"pk": 64, "model": "contenttypes.contenttype", "fields": {"model": "trustedclient", "name": "trusted client", "app_label": "oauth2_provider"}}, {"pk": 75, "model": "contenttypes.contenttype", "fields": {"model": "notificationtype", "name": "type", "app_label": "django_notify"}}, {"pk": 68, "model": "contenttypes.contenttype", "fields": {"model": "urlpath", "name": "URL path", "app_label": "wiki"}}, {"pk": 3, "model": "contenttypes.contenttype", "fields": {"model": "user", "name": "user", "app_label": "auth"}}, {"pk": 84, "model": "contenttypes.contenttype", "fields": {"model": "usercoursetag", "name": "user course tag", "app_label": "user_api"}}, {"pk": 52, "model": "contenttypes.contenttype", "fields": {"model": "userlicense", "name": "user license", "app_label": "licenses"}}, {"pk": 145, "model": "contenttypes.contenttype", "fields": {"model": "usermilestone", "name": "user milestone", "app_label": "milestones"}}, {"pk": 20, "model": "contenttypes.contenttype", "fields": {"model": "useropenid", "name": "user open id", "app_label": "django_openid_auth"}}, {"pk": 85, "model": "contenttypes.contenttype", "fields": {"model": "userorgtag", "name": "user org tag", "app_label": "user_api"}}, {"pk": 83, "model": "contenttypes.contenttype", "fields": {"model": "userpreference", "name": "user preference", "app_label": "user_api"}}, {"pk": 35, "model": "contenttypes.contenttype", "fields": {"model": "userprofile", "name": "user profile", "app_label": "student"}}, {"pk": 36, "model": "contenttypes.contenttype", "fields": {"model": "usersignupsource", "name": "user signup source", "app_label": "student"}}, {"pk": 22, "model": "contenttypes.contenttype", "fields": {"model": "usersocialauth", "name": "user social auth", "app_label": "default"}}, {"pk": 34, "model": "contenttypes.contenttype", "fields": {"model": "userstanding", "name": "user standing", "app_label": "student"}}, {"pk": 37, "model": "contenttypes.contenttype", "fields": {"model": "usertestgroup", "name": "user test group", "app_label": "student"}}, {"pk": 137, "model": "contenttypes.contenttype", "fields": {"model": "video", "name": "video", "app_label": "edxval"}}, {"pk": 146, "model": "contenttypes.contenttype", "fields": {"model": "videouploadconfig", "name": "video upload config", "app_label": "contentstore"}}, {"pk": 13, "model": "contenttypes.contenttype", "fields": {"model": "workerstate", "name": "worker", "app_label": "djcelery"}}, {"pk": 111, "model": "contenttypes.contenttype", "fields": {"model": "xblockasidesconfig", "name": "x block asides config", "app_label": "lms_xblock"}}, {"pk": 30, "model": "contenttypes.contenttype", "fields": {"model": "xmodulestudentinfofield", "name": "x module student info field", "app_label": "courseware"}}, {"pk": 29, "model": "contenttypes.contenttype", "fields": {"model": "xmodulestudentprefsfield", "name": "x module student prefs field", "app_label": "courseware"}}, {"pk": 28, "model": "contenttypes.contenttype", "fields": {"model": "xmoduleuserstatesummaryfield", "name": "x module user state summary field", "app_label": "courseware"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 1, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0001_initial"}}, {"pk": 2, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0002_add_indexes"}}, {"pk": 3, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0003_done_grade_cache"}}, {"pk": 4, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0004_add_field_studentmodule_course_id"}}, {"pk": 5, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0005_auto__add_offlinecomputedgrade__add_unique_offlinecomputedgrade_user_c"}}, {"pk": 6, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0006_create_student_module_history"}}, {"pk": 7, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:15Z", "app_name": "courseware", "migration": "0007_allow_null_version_in_history"}}, {"pk": 8, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0008_add_xmodule_storage"}}, {"pk": 9, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0009_add_field_default"}}, {"pk": 10, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "courseware", "migration": "0010_rename_xblock_field_content_to_user_state_summary"}}, {"pk": 11, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "student", "migration": "0001_initial"}}, {"pk": 12, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:16Z", "app_name": "student", "migration": "0002_text_to_varchar_and_indexes"}}, {"pk": 13, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0003_auto__add_usertestgroup"}}, {"pk": 14, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0004_add_email_index"}}, {"pk": 15, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0005_name_change"}}, {"pk": 16, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0006_expand_meta_field"}}, {"pk": 17, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0007_convert_to_utf8"}}, {"pk": 18, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0008__auto__add_courseregistration"}}, {"pk": 19, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0009_auto__del_courseregistration__add_courseenrollment"}}, {"pk": 20, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0010_auto__chg_field_courseenrollment_course_id"}}, {"pk": 21, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0011_auto__chg_field_courseenrollment_user__del_unique_courseenrollment_use"}}, {"pk": 22, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0012_auto__add_field_userprofile_gender__add_field_userprofile_date_of_birt"}}, {"pk": 23, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0013_auto__chg_field_userprofile_meta"}}, {"pk": 24, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0014_auto__del_courseenrollment"}}, {"pk": 25, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0015_auto__add_courseenrollment__add_unique_courseenrollment_user_course_id"}}, {"pk": 26, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0016_auto__add_field_courseenrollment_date__chg_field_userprofile_country"}}, {"pk": 27, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0017_rename_date_to_created"}}, {"pk": 28, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0018_auto"}}, {"pk": 29, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:17Z", "app_name": "student", "migration": "0019_create_approved_demographic_fields_fall_2012"}}, {"pk": 30, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0020_add_test_center_user"}}, {"pk": 31, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0021_remove_askbot"}}, {"pk": 32, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0022_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_"}}, {"pk": 33, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0023_add_test_center_registration"}}, {"pk": 34, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0024_add_allow_certificate"}}, {"pk": 35, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0025_auto__add_field_courseenrollmentallowed_auto_enroll"}}, {"pk": 36, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0026_auto__remove_index_student_testcenterregistration_accommodation_request"}}, {"pk": 37, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:18Z", "app_name": "student", "migration": "0027_add_active_flag_and_mode_to_courseware_enrollment"}}, {"pk": 38, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0028_auto__add_userstanding"}}, {"pk": 39, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0029_add_lookup_table_between_user_and_anonymous_student_id"}}, {"pk": 40, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0029_remove_pearson"}}, {"pk": 41, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0030_auto__chg_field_anonymoususerid_anonymous_user_id"}}, {"pk": 42, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0031_drop_student_anonymoususerid_temp_archive"}}, {"pk": 43, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0032_add_field_UserProfile_country_add_field_UserProfile_city"}}, {"pk": 44, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0032_auto__add_loginfailures"}}, {"pk": 45, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0033_auto__add_passwordhistory"}}, {"pk": 46, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:19Z", "app_name": "student", "migration": "0034_auto__add_courseaccessrole"}}, {"pk": 47, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0035_access_roles"}}, {"pk": 48, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0036_access_roles_orgless"}}, {"pk": 49, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0037_auto__add_courseregistrationcode"}}, {"pk": 50, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0038_auto__add_usersignupsource"}}, {"pk": 51, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0039_auto__del_courseregistrationcode"}}, {"pk": 52, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0040_auto__del_field_usersignupsource_user_id__add_field_usersignupsource_u"}}, {"pk": 53, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0041_add_dashboard_config"}}, {"pk": 54, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "student", "migration": "0042_grant_sales_admin_roles"}}, {"pk": 55, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "track", "migration": "0001_initial"}}, {"pk": 56, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:20Z", "app_name": "track", "migration": "0002_auto__add_field_trackinglog_host__chg_field_trackinglog_event_type__ch"}}, {"pk": 57, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0001_added_generatedcertificates"}}, {"pk": 58, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0002_auto__add_field_generatedcertificate_download_url"}}, {"pk": 59, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0003_auto__add_field_generatedcertificate_enabled"}}, {"pk": 60, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0004_auto__add_field_generatedcertificate_graded_certificate_id__add_field_"}}, {"pk": 61, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0005_auto__add_field_generatedcertificate_name"}}, {"pk": 62, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0006_auto__chg_field_generatedcertificate_certificate_id"}}, {"pk": 63, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0007_auto__add_revokedcertificate"}}, {"pk": 64, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0008_auto__del_revokedcertificate__del_field_generatedcertificate_name__add"}}, {"pk": 65, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0009_auto__del_field_generatedcertificate_graded_download_url__del_field_ge"}}, {"pk": 66, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0010_auto__del_field_generatedcertificate_enabled__add_field_generatedcerti"}}, {"pk": 67, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0011_auto__del_field_generatedcertificate_certificate_id__add_field_generat"}}, {"pk": 68, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0012_auto__add_field_generatedcertificate_name__add_field_generatedcertific"}}, {"pk": 69, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0013_auto__add_field_generatedcertificate_error_reason"}}, {"pk": 70, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0014_adding_whitelist"}}, {"pk": 71, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:21Z", "app_name": "certificates", "migration": "0015_adding_mode_for_verified_certs"}}, {"pk": 72, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "instructor_task", "migration": "0001_initial"}}, {"pk": 73, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "instructor_task", "migration": "0002_add_subtask_field"}}, {"pk": 74, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "licenses", "migration": "0001_initial"}}, {"pk": 75, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "course_groups", "migration": "0001_initial"}}, {"pk": 76, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:22Z", "app_name": "course_groups", "migration": "0002_add_model_CourseUserGroupPartitionGroup"}}, {"pk": 77, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0001_initial"}}, {"pk": 78, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0002_change_field_names"}}, {"pk": 79, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0003_add_optout_user"}}, {"pk": 80, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0004_migrate_optout_user"}}, {"pk": 81, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0005_remove_optout_email"}}, {"pk": 82, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0006_add_course_email_template"}}, {"pk": 83, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0007_load_course_email_template"}}, {"pk": 84, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0008_add_course_authorizations"}}, {"pk": 85, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0009_force_unique_course_ids"}}, {"pk": 86, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "bulk_email", "migration": "0010_auto__chg_field_optout_course_id__add_field_courseemail_template_name_"}}, {"pk": 87, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:23Z", "app_name": "external_auth", "migration": "0001_initial"}}, {"pk": 88, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0001_initial"}}, {"pk": 89, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0002_auto__chg_field_client_user"}}, {"pk": 90, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0003_auto__add_field_client_name"}}, {"pk": 91, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2", "migration": "0004_auto__add_index_accesstoken_token"}}, {"pk": 92, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:24Z", "app_name": "oauth2_provider", "migration": "0001_initial"}}, {"pk": 93, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0001_initial"}}, {"pk": 94, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0002_auto__add_field_articleplugin_created"}}, {"pk": 95, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0003_auto__add_field_urlpath_article"}}, {"pk": 96, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0004_populate_urlpath__article"}}, {"pk": 97, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:25Z", "app_name": "wiki", "migration": "0005_auto__chg_field_urlpath_article"}}, {"pk": 98, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0006_auto__add_attachmentrevision__add_image__add_attachment"}}, {"pk": 99, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0007_auto__add_articlesubscription"}}, {"pk": 100, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0008_auto__add_simpleplugin__add_revisionpluginrevision__add_imagerevision_"}}, {"pk": 101, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0009_auto__add_field_imagerevision_width__add_field_imagerevision_height"}}, {"pk": 102, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0010_auto__chg_field_imagerevision_image"}}, {"pk": 103, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:26Z", "app_name": "wiki", "migration": "0011_auto__chg_field_imagerevision_width__chg_field_imagerevision_height"}}, {"pk": 104, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "django_notify", "migration": "0001_initial"}}, {"pk": 105, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "notifications", "migration": "0001_initial"}}, {"pk": 106, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:27Z", "app_name": "foldit", "migration": "0001_initial"}}, {"pk": 107, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:28Z", "app_name": "django_comment_client", "migration": "0001_initial"}}, {"pk": 108, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:28Z", "app_name": "django_comment_common", "migration": "0001_initial"}}, {"pk": 109, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "notes", "migration": "0001_initial"}}, {"pk": 110, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "splash", "migration": "0001_initial"}}, {"pk": 111, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "splash", "migration": "0002_auto__add_field_splashconfig_unaffected_url_paths"}}, {"pk": 112, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:29Z", "app_name": "user_api", "migration": "0001_initial"}}, {"pk": 113, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0002_auto__add_usercoursetags__add_unique_usercoursetags_user_course_id_key"}}, {"pk": 114, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0003_rename_usercoursetags"}}, {"pk": 115, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "user_api", "migration": "0004_auto__add_userorgtag__add_unique_userorgtag_user_org_key__chg_field_us"}}, {"pk": 116, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0001_initial"}}, {"pk": 117, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0002_auto__add_field_paidcourseregistration_mode"}}, {"pk": 118, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0003_auto__del_field_orderitem_line_cost"}}, {"pk": 119, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0004_auto__add_field_orderitem_fulfilled_time"}}, {"pk": 120, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0005_auto__add_paidcourseregistrationannotation__add_field_orderitem_report"}}, {"pk": 121, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0006_auto__add_field_order_refunded_time__add_field_orderitem_refund_reques"}}, {"pk": 122, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:30Z", "app_name": "shoppingcart", "migration": "0007_auto__add_field_orderitem_service_fee"}}, {"pk": 123, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0008_auto__add_coupons__add_couponredemption__chg_field_certificateitem_cou"}}, {"pk": 124, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0009_auto__del_coupons__add_courseregistrationcode__add_coupon__chg_field_c"}}, {"pk": 125, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0010_auto__add_registrationcoderedemption__del_field_courseregistrationcode"}}, {"pk": 126, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0011_auto__add_invoice__add_field_courseregistrationcode_invoice"}}, {"pk": 127, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:31Z", "app_name": "shoppingcart", "migration": "0012_auto__del_field_courseregistrationcode_transaction_group_name__del_fie"}}, {"pk": 128, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0013_auto__add_field_invoice_is_valid"}}, {"pk": 129, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0014_auto__del_field_invoice_tax_id__add_field_invoice_address_line_1__add_"}}, {"pk": 130, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0015_auto__del_field_invoice_purchase_order_number__del_field_invoice_compa"}}, {"pk": 131, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0016_auto__del_field_invoice_company_email__del_field_invoice_company_refer"}}, {"pk": 132, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0017_auto__add_field_courseregistrationcode_order__chg_field_registrationco"}}, {"pk": 133, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0018_auto__add_donation"}}, {"pk": 134, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:32Z", "app_name": "shoppingcart", "migration": "0019_auto__add_donationconfiguration"}}, {"pk": 135, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0020_auto__add_courseregcodeitem__add_courseregcodeitemannotation__add_fiel"}}, {"pk": 136, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0021_auto__add_field_orderitem_created__add_field_orderitem_modified"}}, {"pk": 137, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0022_auto__add_field_registrationcoderedemption_course_enrollment__add_fiel"}}, {"pk": 138, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0023_auto__add_field_coupon_expiration_date"}}, {"pk": 139, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "shoppingcart", "migration": "0024_auto__add_field_courseregistrationcode_mode_slug"}}, {"pk": 140, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0001_initial"}}, {"pk": 141, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0002_auto__add_field_coursemode_currency"}}, {"pk": 142, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:33Z", "app_name": "course_modes", "migration": "0003_auto__add_unique_coursemode_course_id_currency_mode_slug"}}, {"pk": 143, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0004_auto__add_field_coursemode_expiration_date"}}, {"pk": 144, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0005_auto__add_field_coursemode_expiration_datetime"}}, {"pk": 145, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0006_expiration_date_to_datetime"}}, {"pk": 146, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0007_add_description"}}, {"pk": 147, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "course_modes", "migration": "0007_auto__add_coursemodesarchive__chg_field_coursemode_course_id"}}, {"pk": 148, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0001_initial"}}, {"pk": 149, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0002_auto__add_field_softwaresecurephotoverification_window"}}, {"pk": 150, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:34Z", "app_name": "verify_student", "migration": "0003_auto__add_field_softwaresecurephotoverification_display"}}, {"pk": 151, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "dark_lang", "migration": "0001_initial"}}, {"pk": 152, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "dark_lang", "migration": "0002_enable_on_install"}}, {"pk": 153, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "reverification", "migration": "0001_initial"}}, {"pk": 154, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:35Z", "app_name": "embargo", "migration": "0001_initial"}}, {"pk": 155, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "course_action_state", "migration": "0001_initial"}}, {"pk": 156, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "course_action_state", "migration": "0002_add_rerun_display_name"}}, {"pk": 157, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:36Z", "app_name": "survey", "migration": "0001_initial"}}, {"pk": 158, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "lms_xblock", "migration": "0001_initial"}}, {"pk": 159, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0001_initial"}}, {"pk": 160, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0002_auto__add_field_answer_course_id__chg_field_answer_student_id"}}, {"pk": 161, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0003_auto__del_unique_answer_student_id_name__add_unique_answer_course_id_s"}}, {"pk": 162, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0004_auto__add_lightchild__add_unique_lightchild_student_id_course_id_name"}}, {"pk": 163, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:37Z", "app_name": "mentoring", "migration": "0005_auto__chg_field_lightchild_name"}}, {"pk": 164, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0001_initial"}}, {"pk": 165, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0002_auto__add_scoresummary"}}, {"pk": 166, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0003_auto__del_field_submission_answer__add_field_submission_raw_answer"}}, {"pk": 167, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:38Z", "app_name": "submissions", "migration": "0004_auto__add_field_score_reset"}}, {"pk": 168, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0001_initial"}}, {"pk": 169, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0002_auto__add_assessmentfeedbackoption__del_field_assessmentfeedback_feedb"}}, {"pk": 170, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0003_add_index_pw_course_item_student"}}, {"pk": 171, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0004_auto__add_field_peerworkflow_graded_count"}}, {"pk": 172, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0005_auto__del_field_peerworkflow_graded_count__add_field_peerworkflow_grad"}}, {"pk": 173, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0006_auto__add_field_assessmentpart_feedback"}}, {"pk": 174, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:39Z", "app_name": "assessment", "migration": "0007_auto__chg_field_assessmentpart_feedback"}}, {"pk": 175, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0008_student_training"}}, {"pk": 176, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0009_auto__add_unique_studenttrainingworkflowitem_order_num_workflow"}}, {"pk": 177, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0010_auto__add_unique_studenttrainingworkflow_submission_uuid"}}, {"pk": 178, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0011_ai_training"}}, {"pk": 179, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0012_move_algorithm_id_to_classifier_set"}}, {"pk": 180, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0013_auto__add_field_aigradingworkflow_essay_text"}}, {"pk": 181, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0014_auto__add_field_aitrainingworkflow_item_id__add_field_aitrainingworkfl"}}, {"pk": 182, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:40Z", "app_name": "assessment", "migration": "0015_auto__add_unique_aitrainingworkflow_uuid__add_unique_aigradingworkflow"}}, {"pk": 183, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0016_auto__add_field_aiclassifierset_course_id__add_field_aiclassifierset_i"}}, {"pk": 184, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0016_auto__add_field_rubric_structure_hash"}}, {"pk": 185, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0017_rubric_structure_hash"}}, {"pk": 186, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0018_auto__add_field_assessmentpart_criterion"}}, {"pk": 187, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0019_assessmentpart_criterion_field"}}, {"pk": 188, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0020_assessmentpart_criterion_not_null"}}, {"pk": 189, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0021_assessmentpart_option_nullable"}}, {"pk": 190, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0022__add_label_fields"}}, {"pk": 191, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:41Z", "app_name": "assessment", "migration": "0023_assign_criteria_and_option_labels"}}, {"pk": 192, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "assessment", "migration": "0024_auto__chg_field_assessmentpart_criterion"}}, {"pk": 193, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0001_initial"}}, {"pk": 194, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0002_auto__add_field_assessmentworkflow_course_id__add_field_assessmentwork"}}, {"pk": 195, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "workflow", "migration": "0003_auto__add_assessmentworkflowstep"}}, {"pk": 196, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:42Z", "app_name": "edxval", "migration": "0001_initial"}}, {"pk": 197, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "edxval", "migration": "0002_default_profiles"}}, {"pk": 198, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "edxval", "migration": "0003_status_and_created_fields"}}, {"pk": 199, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "milestones", "migration": "0001_initial"}}, {"pk": 200, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "milestones", "migration": "0002_seed_relationship_types"}}, {"pk": 201, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:43Z", "app_name": "django_extensions", "migration": "0001_empty"}}, {"pk": 202, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "contentstore", "migration": "0001_initial"}}, {"pk": 203, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "course_creators", "migration": "0001_initial"}}, {"pk": 204, "model": "south.migrationhistory", "fields": {"applied": "2015-01-15T03:15:46Z", "app_name": "xblock_config", "migration": "0001_initial"}}, {"pk": 1, "model": "edxval.profile", "fields": {"width": 1280, "profile_name": "desktop_mp4", "extension": "mp4", "height": 720}}, {"pk": 2, "model": "edxval.profile", "fields": {"width": 1280, "profile_name": "desktop_webm", "extension": "webm", "height": 720}}, {"pk": 3, "model": "edxval.profile", "fields": {"width": 960, "profile_name": "mobile_high", "extension": "mp4", "height": 540}}, {"pk": 4, "model": "edxval.profile", "fields": {"width": 640, "profile_name": "mobile_low", "extension": "mp4", "height": 360}}, {"pk": 5, "model": "edxval.profile", "fields": {"width": 1920, "profile_name": "youtube", "extension": "mp4", "height": 1080}}, {"pk": 1, "model": "milestones.milestonerelationshiptype", "fields": {"active": true, "description": "Autogenerated milestone relationship type \"fulfills\"", "modified": "2015-01-15T03:15:43Z", "name": "fulfills", "created": "2015-01-15T03:15:43Z"}}, {"pk": 2, "model": "milestones.milestonerelationshiptype", "fields": {"active": true, "description": "Autogenerated milestone relationship type \"requires\"", "modified": "2015-01-15T03:15:43Z", "name": "requires", "created": "2015-01-15T03:15:43Z"}}, {"pk": 61, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 21}}, {"pk": 62, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 21}}, {"pk": 63, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 21}}, {"pk": 394, "model": "auth.permission", "fields": {"codename": "add_aiclassifier", "name": "Can add ai classifier", "content_type": 131}}, {"pk": 395, "model": "auth.permission", "fields": {"codename": "change_aiclassifier", "name": "Can change ai classifier", "content_type": 131}}, {"pk": 396, "model": "auth.permission", "fields": {"codename": "delete_aiclassifier", "name": "Can delete ai classifier", "content_type": 131}}, {"pk": 391, "model": "auth.permission", "fields": {"codename": "add_aiclassifierset", "name": "Can add ai classifier set", "content_type": 130}}, {"pk": 392, "model": "auth.permission", "fields": {"codename": "change_aiclassifierset", "name": "Can change ai classifier set", "content_type": 130}}, {"pk": 393, "model": "auth.permission", "fields": {"codename": "delete_aiclassifierset", "name": "Can delete ai classifier set", "content_type": 130}}, {"pk": 400, "model": "auth.permission", "fields": {"codename": "add_aigradingworkflow", "name": "Can add ai grading workflow", "content_type": 133}}, {"pk": 401, "model": "auth.permission", "fields": {"codename": "change_aigradingworkflow", "name": "Can change ai grading workflow", "content_type": 133}}, {"pk": 402, "model": "auth.permission", "fields": {"codename": "delete_aigradingworkflow", "name": "Can delete ai grading workflow", "content_type": 133}}, {"pk": 397, "model": "auth.permission", "fields": {"codename": "add_aitrainingworkflow", "name": "Can add ai training workflow", "content_type": 132}}, {"pk": 398, "model": "auth.permission", "fields": {"codename": "change_aitrainingworkflow", "name": "Can change ai training workflow", "content_type": 132}}, {"pk": 399, "model": "auth.permission", "fields": {"codename": "delete_aitrainingworkflow", "name": "Can delete ai training workflow", "content_type": 132}}, {"pk": 364, "model": "auth.permission", "fields": {"codename": "add_assessment", "name": "Can add assessment", "content_type": 121}}, {"pk": 365, "model": "auth.permission", "fields": {"codename": "change_assessment", "name": "Can change assessment", "content_type": 121}}, {"pk": 366, "model": "auth.permission", "fields": {"codename": "delete_assessment", "name": "Can delete assessment", "content_type": 121}}, {"pk": 373, "model": "auth.permission", "fields": {"codename": "add_assessmentfeedback", "name": "Can add assessment feedback", "content_type": 124}}, {"pk": 374, "model": "auth.permission", "fields": {"codename": "change_assessmentfeedback", "name": "Can change assessment feedback", "content_type": 124}}, {"pk": 375, "model": "auth.permission", "fields": {"codename": "delete_assessmentfeedback", "name": "Can delete assessment feedback", "content_type": 124}}, {"pk": 370, "model": "auth.permission", "fields": {"codename": "add_assessmentfeedbackoption", "name": "Can add assessment feedback option", "content_type": 123}}, {"pk": 371, "model": "auth.permission", "fields": {"codename": "change_assessmentfeedbackoption", "name": "Can change assessment feedback option", "content_type": 123}}, {"pk": 372, "model": "auth.permission", "fields": {"codename": "delete_assessmentfeedbackoption", "name": "Can delete assessment feedback option", "content_type": 123}}, {"pk": 367, "model": "auth.permission", "fields": {"codename": "add_assessmentpart", "name": "Can add assessment part", "content_type": 122}}, {"pk": 368, "model": "auth.permission", "fields": {"codename": "change_assessmentpart", "name": "Can change assessment part", "content_type": 122}}, {"pk": 369, "model": "auth.permission", "fields": {"codename": "delete_assessmentpart", "name": "Can delete assessment part", "content_type": 122}}, {"pk": 358, "model": "auth.permission", "fields": {"codename": "add_criterion", "name": "Can add criterion", "content_type": 119}}, {"pk": 359, "model": "auth.permission", "fields": {"codename": "change_criterion", "name": "Can change criterion", "content_type": 119}}, {"pk": 360, "model": "auth.permission", "fields": {"codename": "delete_criterion", "name": "Can delete criterion", "content_type": 119}}, {"pk": 361, "model": "auth.permission", "fields": {"codename": "add_criterionoption", "name": "Can add criterion option", "content_type": 120}}, {"pk": 362, "model": "auth.permission", "fields": {"codename": "change_criterionoption", "name": "Can change criterion option", "content_type": 120}}, {"pk": 363, "model": "auth.permission", "fields": {"codename": "delete_criterionoption", "name": "Can delete criterion option", "content_type": 120}}, {"pk": 376, "model": "auth.permission", "fields": {"codename": "add_peerworkflow", "name": "Can add peer workflow", "content_type": 125}}, {"pk": 377, "model": "auth.permission", "fields": {"codename": "change_peerworkflow", "name": "Can change peer workflow", "content_type": 125}}, {"pk": 378, "model": "auth.permission", "fields": {"codename": "delete_peerworkflow", "name": "Can delete peer workflow", "content_type": 125}}, {"pk": 379, "model": "auth.permission", "fields": {"codename": "add_peerworkflowitem", "name": "Can add peer workflow item", "content_type": 126}}, {"pk": 380, "model": "auth.permission", "fields": {"codename": "change_peerworkflowitem", "name": "Can change peer workflow item", "content_type": 126}}, {"pk": 381, "model": "auth.permission", "fields": {"codename": "delete_peerworkflowitem", "name": "Can delete peer workflow item", "content_type": 126}}, {"pk": 355, "model": "auth.permission", "fields": {"codename": "add_rubric", "name": "Can add rubric", "content_type": 118}}, {"pk": 356, "model": "auth.permission", "fields": {"codename": "change_rubric", "name": "Can change rubric", "content_type": 118}}, {"pk": 357, "model": "auth.permission", "fields": {"codename": "delete_rubric", "name": "Can delete rubric", "content_type": 118}}, {"pk": 385, "model": "auth.permission", "fields": {"codename": "add_studenttrainingworkflow", "name": "Can add student training workflow", "content_type": 128}}, {"pk": 386, "model": "auth.permission", "fields": {"codename": "change_studenttrainingworkflow", "name": "Can change student training workflow", "content_type": 128}}, {"pk": 387, "model": "auth.permission", "fields": {"codename": "delete_studenttrainingworkflow", "name": "Can delete student training workflow", "content_type": 128}}, {"pk": 388, "model": "auth.permission", "fields": {"codename": "add_studenttrainingworkflowitem", "name": "Can add student training workflow item", "content_type": 129}}, {"pk": 389, "model": "auth.permission", "fields": {"codename": "change_studenttrainingworkflowitem", "name": "Can change student training workflow item", "content_type": 129}}, {"pk": 390, "model": "auth.permission", "fields": {"codename": "delete_studenttrainingworkflowitem", "name": "Can delete student training workflow item", "content_type": 129}}, {"pk": 382, "model": "auth.permission", "fields": {"codename": "add_trainingexample", "name": "Can add training example", "content_type": 127}}, {"pk": 383, "model": "auth.permission", "fields": {"codename": "change_trainingexample", "name": "Can change training example", "content_type": 127}}, {"pk": 384, "model": "auth.permission", "fields": {"codename": "delete_trainingexample", "name": "Can delete training example", "content_type": 127}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 172, "model": "auth.permission", "fields": {"codename": "add_courseauthorization", "name": "Can add course authorization", "content_type": 58}}, {"pk": 173, "model": "auth.permission", "fields": {"codename": "change_courseauthorization", "name": "Can change course authorization", "content_type": 58}}, {"pk": 174, "model": "auth.permission", "fields": {"codename": "delete_courseauthorization", "name": "Can delete course authorization", "content_type": 58}}, {"pk": 163, "model": "auth.permission", "fields": {"codename": "add_courseemail", "name": "Can add course email", "content_type": 55}}, {"pk": 164, "model": "auth.permission", "fields": {"codename": "change_courseemail", "name": "Can change course email", "content_type": 55}}, {"pk": 165, "model": "auth.permission", "fields": {"codename": "delete_courseemail", "name": "Can delete course email", "content_type": 55}}, {"pk": 169, "model": "auth.permission", "fields": {"codename": "add_courseemailtemplate", "name": "Can add course email template", "content_type": 57}}, {"pk": 170, "model": "auth.permission", "fields": {"codename": "change_courseemailtemplate", "name": "Can change course email template", "content_type": 57}}, {"pk": 171, "model": "auth.permission", "fields": {"codename": "delete_courseemailtemplate", "name": "Can delete course email template", "content_type": 57}}, {"pk": 166, "model": "auth.permission", "fields": {"codename": "add_optout", "name": "Can add optout", "content_type": 56}}, {"pk": 167, "model": "auth.permission", "fields": {"codename": "change_optout", "name": "Can change optout", "content_type": 56}}, {"pk": 168, "model": "auth.permission", "fields": {"codename": "delete_optout", "name": "Can delete optout", "content_type": 56}}, {"pk": 142, "model": "auth.permission", "fields": {"codename": "add_certificatewhitelist", "name": "Can add certificate whitelist", "content_type": 48}}, {"pk": 143, "model": "auth.permission", "fields": {"codename": "change_certificatewhitelist", "name": "Can change certificate whitelist", "content_type": 48}}, {"pk": 144, "model": "auth.permission", "fields": {"codename": "delete_certificatewhitelist", "name": "Can delete certificate whitelist", "content_type": 48}}, {"pk": 145, "model": "auth.permission", "fields": {"codename": "add_generatedcertificate", "name": "Can add generated certificate", "content_type": 49}}, {"pk": 146, "model": "auth.permission", "fields": {"codename": "change_generatedcertificate", "name": "Can change generated certificate", "content_type": 49}}, {"pk": 147, "model": "auth.permission", "fields": {"codename": "delete_generatedcertificate", "name": "Can delete generated certificate", "content_type": 49}}, {"pk": 46, "model": "auth.permission", "fields": {"codename": "add_servercircuit", "name": "Can add server circuit", "content_type": 16}}, {"pk": 47, "model": "auth.permission", "fields": {"codename": "change_servercircuit", "name": "Can change server circuit", "content_type": 16}}, {"pk": 48, "model": "auth.permission", "fields": {"codename": "delete_servercircuit", "name": "Can delete server circuit", "content_type": 16}}, {"pk": 439, "model": "auth.permission", "fields": {"codename": "add_videouploadconfig", "name": "Can add video upload config", "content_type": 146}}, {"pk": 440, "model": "auth.permission", "fields": {"codename": "change_videouploadconfig", "name": "Can change video upload config", "content_type": 146}}, {"pk": 441, "model": "auth.permission", "fields": {"codename": "delete_videouploadconfig", "name": "Can delete video upload config", "content_type": 146}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 4}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 4}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 4}}, {"pk": 91, "model": "auth.permission", "fields": {"codename": "add_offlinecomputedgrade", "name": "Can add offline computed grade", "content_type": 31}}, {"pk": 92, "model": "auth.permission", "fields": {"codename": "change_offlinecomputedgrade", "name": "Can change offline computed grade", "content_type": 31}}, {"pk": 93, "model": "auth.permission", "fields": {"codename": "delete_offlinecomputedgrade", "name": "Can delete offline computed grade", "content_type": 31}}, {"pk": 94, "model": "auth.permission", "fields": {"codename": "add_offlinecomputedgradelog", "name": "Can add offline computed grade log", "content_type": 32}}, {"pk": 95, "model": "auth.permission", "fields": {"codename": "change_offlinecomputedgradelog", "name": "Can change offline computed grade log", "content_type": 32}}, {"pk": 96, "model": "auth.permission", "fields": {"codename": "delete_offlinecomputedgradelog", "name": "Can delete offline computed grade log", "content_type": 32}}, {"pk": 76, "model": "auth.permission", "fields": {"codename": "add_studentmodule", "name": "Can add student module", "content_type": 26}}, {"pk": 77, "model": "auth.permission", "fields": {"codename": "change_studentmodule", "name": "Can change student module", "content_type": 26}}, {"pk": 78, "model": "auth.permission", "fields": {"codename": "delete_studentmodule", "name": "Can delete student module", "content_type": 26}}, {"pk": 79, "model": "auth.permission", "fields": {"codename": "add_studentmodulehistory", "name": "Can add student module history", "content_type": 27}}, {"pk": 80, "model": "auth.permission", "fields": {"codename": "change_studentmodulehistory", "name": "Can change student module history", "content_type": 27}}, {"pk": 81, "model": "auth.permission", "fields": {"codename": "delete_studentmodulehistory", "name": "Can delete student module history", "content_type": 27}}, {"pk": 88, "model": "auth.permission", "fields": {"codename": "add_xmodulestudentinfofield", "name": "Can add x module student info field", "content_type": 30}}, {"pk": 89, "model": "auth.permission", "fields": {"codename": "change_xmodulestudentinfofield", "name": "Can change x module student info field", "content_type": 30}}, {"pk": 90, "model": "auth.permission", "fields": {"codename": "delete_xmodulestudentinfofield", "name": "Can delete x module student info field", "content_type": 30}}, {"pk": 85, "model": "auth.permission", "fields": {"codename": "add_xmodulestudentprefsfield", "name": "Can add x module student prefs field", "content_type": 29}}, {"pk": 86, "model": "auth.permission", "fields": {"codename": "change_xmodulestudentprefsfield", "name": "Can change x module student prefs field", "content_type": 29}}, {"pk": 87, "model": "auth.permission", "fields": {"codename": "delete_xmodulestudentprefsfield", "name": "Can delete x module student prefs field", "content_type": 29}}, {"pk": 82, "model": "auth.permission", "fields": {"codename": "add_xmoduleuserstatesummaryfield", "name": "Can add x module user state summary field", "content_type": 28}}, {"pk": 83, "model": "auth.permission", "fields": {"codename": "change_xmoduleuserstatesummaryfield", "name": "Can change x module user state summary field", "content_type": 28}}, {"pk": 84, "model": "auth.permission", "fields": {"codename": "delete_xmoduleuserstatesummaryfield", "name": "Can delete x module user state summary field", "content_type": 28}}, {"pk": 325, "model": "auth.permission", "fields": {"codename": "add_coursererunstate", "name": "Can add course rerun state", "content_type": 108}}, {"pk": 326, "model": "auth.permission", "fields": {"codename": "change_coursererunstate", "name": "Can change course rerun state", "content_type": 108}}, {"pk": 327, "model": "auth.permission", "fields": {"codename": "delete_coursererunstate", "name": "Can delete course rerun state", "content_type": 108}}, {"pk": 442, "model": "auth.permission", "fields": {"codename": "add_coursecreator", "name": "Can add course creator", "content_type": 147}}, {"pk": 443, "model": "auth.permission", "fields": {"codename": "change_coursecreator", "name": "Can change course creator", "content_type": 147}}, {"pk": 444, "model": "auth.permission", "fields": {"codename": "delete_coursecreator", "name": "Can delete course creator", "content_type": 147}}, {"pk": 157, "model": "auth.permission", "fields": {"codename": "add_courseusergroup", "name": "Can add course user group", "content_type": 53}}, {"pk": 158, "model": "auth.permission", "fields": {"codename": "change_courseusergroup", "name": "Can change course user group", "content_type": 53}}, {"pk": 159, "model": "auth.permission", "fields": {"codename": "delete_courseusergroup", "name": "Can delete course user group", "content_type": 53}}, {"pk": 160, "model": "auth.permission", "fields": {"codename": "add_courseusergrouppartitiongroup", "name": "Can add course user group partition group", "content_type": 54}}, {"pk": 161, "model": "auth.permission", "fields": {"codename": "change_courseusergrouppartitiongroup", "name": "Can change course user group partition group", "content_type": 54}}, {"pk": 162, "model": "auth.permission", "fields": {"codename": "delete_courseusergrouppartitiongroup", "name": "Can delete course user group partition group", "content_type": 54}}, {"pk": 301, "model": "auth.permission", "fields": {"codename": "add_coursemode", "name": "Can add course mode", "content_type": 100}}, {"pk": 302, "model": "auth.permission", "fields": {"codename": "change_coursemode", "name": "Can change course mode", "content_type": 100}}, {"pk": 303, "model": "auth.permission", "fields": {"codename": "delete_coursemode", "name": "Can delete course mode", "content_type": 100}}, {"pk": 304, "model": "auth.permission", "fields": {"codename": "add_coursemodesarchive", "name": "Can add course modes archive", "content_type": 101}}, {"pk": 305, "model": "auth.permission", "fields": {"codename": "change_coursemodesarchive", "name": "Can change course modes archive", "content_type": 101}}, {"pk": 306, "model": "auth.permission", "fields": {"codename": "delete_coursemodesarchive", "name": "Can delete course modes archive", "content_type": 101}}, {"pk": 310, "model": "auth.permission", "fields": {"codename": "add_darklangconfig", "name": "Can add dark lang config", "content_type": 103}}, {"pk": 311, "model": "auth.permission", "fields": {"codename": "change_darklangconfig", "name": "Can change dark lang config", "content_type": 103}}, {"pk": 312, "model": "auth.permission", "fields": {"codename": "delete_darklangconfig", "name": "Can delete dark lang config", "content_type": 103}}, {"pk": 70, "model": "auth.permission", "fields": {"codename": "add_association", "name": "Can add association", "content_type": 24}}, {"pk": 71, "model": "auth.permission", "fields": {"codename": "change_association", "name": "Can change association", "content_type": 24}}, {"pk": 72, "model": "auth.permission", "fields": {"codename": "delete_association", "name": "Can delete association", "content_type": 24}}, {"pk": 73, "model": "auth.permission", "fields": {"codename": "add_code", "name": "Can add code", "content_type": 25}}, {"pk": 74, "model": "auth.permission", "fields": {"codename": "change_code", "name": "Can change code", "content_type": 25}}, {"pk": 75, "model": "auth.permission", "fields": {"codename": "delete_code", "name": "Can delete code", "content_type": 25}}, {"pk": 67, "model": "auth.permission", "fields": {"codename": "add_nonce", "name": "Can add nonce", "content_type": 23}}, {"pk": 68, "model": "auth.permission", "fields": {"codename": "change_nonce", "name": "Can change nonce", "content_type": 23}}, {"pk": 69, "model": "auth.permission", "fields": {"codename": "delete_nonce", "name": "Can delete nonce", "content_type": 23}}, {"pk": 64, "model": "auth.permission", "fields": {"codename": "add_usersocialauth", "name": "Can add user social auth", "content_type": 22}}, {"pk": 65, "model": "auth.permission", "fields": {"codename": "change_usersocialauth", "name": "Can change user social auth", "content_type": 22}}, {"pk": 66, "model": "auth.permission", "fields": {"codename": "delete_usersocialauth", "name": "Can delete user social auth", "content_type": 22}}, {"pk": 235, "model": "auth.permission", "fields": {"codename": "add_notification", "name": "Can add notification", "content_type": 78}}, {"pk": 236, "model": "auth.permission", "fields": {"codename": "change_notification", "name": "Can change notification", "content_type": 78}}, {"pk": 237, "model": "auth.permission", "fields": {"codename": "delete_notification", "name": "Can delete notification", "content_type": 78}}, {"pk": 226, "model": "auth.permission", "fields": {"codename": "add_notificationtype", "name": "Can add type", "content_type": 75}}, {"pk": 227, "model": "auth.permission", "fields": {"codename": "change_notificationtype", "name": "Can change type", "content_type": 75}}, {"pk": 228, "model": "auth.permission", "fields": {"codename": "delete_notificationtype", "name": "Can delete type", "content_type": 75}}, {"pk": 229, "model": "auth.permission", "fields": {"codename": "add_settings", "name": "Can add settings", "content_type": 76}}, {"pk": 230, "model": "auth.permission", "fields": {"codename": "change_settings", "name": "Can change settings", "content_type": 76}}, {"pk": 231, "model": "auth.permission", "fields": {"codename": "delete_settings", "name": "Can delete settings", "content_type": 76}}, {"pk": 232, "model": "auth.permission", "fields": {"codename": "add_subscription", "name": "Can add subscription", "content_type": 77}}, {"pk": 233, "model": "auth.permission", "fields": {"codename": "change_subscription", "name": "Can change subscription", "content_type": 77}}, {"pk": 234, "model": "auth.permission", "fields": {"codename": "delete_subscription", "name": "Can delete subscription", "content_type": 77}}, {"pk": 55, "model": "auth.permission", "fields": {"codename": "add_association", "name": "Can add association", "content_type": 19}}, {"pk": 56, "model": "auth.permission", "fields": {"codename": "change_association", "name": "Can change association", "content_type": 19}}, {"pk": 57, "model": "auth.permission", "fields": {"codename": "delete_association", "name": "Can delete association", "content_type": 19}}, {"pk": 52, "model": "auth.permission", "fields": {"codename": "add_nonce", "name": "Can add nonce", "content_type": 18}}, {"pk": 53, "model": "auth.permission", "fields": {"codename": "change_nonce", "name": "Can change nonce", "content_type": 18}}, {"pk": 54, "model": "auth.permission", "fields": {"codename": "delete_nonce", "name": "Can delete nonce", "content_type": 18}}, {"pk": 58, "model": "auth.permission", "fields": {"codename": "add_useropenid", "name": "Can add user open id", "content_type": 20}}, {"pk": 59, "model": "auth.permission", "fields": {"codename": "change_useropenid", "name": "Can change user open id", "content_type": 20}}, {"pk": 60, "model": "auth.permission", "fields": {"codename": "delete_useropenid", "name": "Can delete user open id", "content_type": 20}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_crontabschedule", "name": "Can add crontab", "content_type": 10}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_crontabschedule", "name": "Can change crontab", "content_type": 10}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_crontabschedule", "name": "Can delete crontab", "content_type": 10}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_intervalschedule", "name": "Can add interval", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_intervalschedule", "name": "Can change interval", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_intervalschedule", "name": "Can delete interval", "content_type": 9}}, {"pk": 34, "model": "auth.permission", "fields": {"codename": "add_periodictask", "name": "Can add periodic task", "content_type": 12}}, {"pk": 35, "model": "auth.permission", "fields": {"codename": "change_periodictask", "name": "Can change periodic task", "content_type": 12}}, {"pk": 36, "model": "auth.permission", "fields": {"codename": "delete_periodictask", "name": "Can delete periodic task", "content_type": 12}}, {"pk": 31, "model": "auth.permission", "fields": {"codename": "add_periodictasks", "name": "Can add periodic tasks", "content_type": 11}}, {"pk": 32, "model": "auth.permission", "fields": {"codename": "change_periodictasks", "name": "Can change periodic tasks", "content_type": 11}}, {"pk": 33, "model": "auth.permission", "fields": {"codename": "delete_periodictasks", "name": "Can delete periodic tasks", "content_type": 11}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_taskmeta", "name": "Can add task state", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_taskmeta", "name": "Can change task state", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_taskmeta", "name": "Can delete task state", "content_type": 7}}, {"pk": 22, "model": "auth.permission", "fields": {"codename": "add_tasksetmeta", "name": "Can add saved group result", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_tasksetmeta", "name": "Can change saved group result", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_tasksetmeta", "name": "Can delete saved group result", "content_type": 8}}, {"pk": 40, "model": "auth.permission", "fields": {"codename": "add_taskstate", "name": "Can add task", "content_type": 14}}, {"pk": 41, "model": "auth.permission", "fields": {"codename": "change_taskstate", "name": "Can change task", "content_type": 14}}, {"pk": 42, "model": "auth.permission", "fields": {"codename": "delete_taskstate", "name": "Can delete task", "content_type": 14}}, {"pk": 37, "model": "auth.permission", "fields": {"codename": "add_workerstate", "name": "Can add worker", "content_type": 13}}, {"pk": 38, "model": "auth.permission", "fields": {"codename": "change_workerstate", "name": "Can change worker", "content_type": 13}}, {"pk": 39, "model": "auth.permission", "fields": {"codename": "delete_workerstate", "name": "Can delete worker", "content_type": 13}}, {"pk": 415, "model": "auth.permission", "fields": {"codename": "add_coursevideo", "name": "Can add course video", "content_type": 138}}, {"pk": 416, "model": "auth.permission", "fields": {"codename": "change_coursevideo", "name": "Can change course video", "content_type": 138}}, {"pk": 417, "model": "auth.permission", "fields": {"codename": "delete_coursevideo", "name": "Can delete course video", "content_type": 138}}, {"pk": 418, "model": "auth.permission", "fields": {"codename": "add_encodedvideo", "name": "Can add encoded video", "content_type": 139}}, {"pk": 419, "model": "auth.permission", "fields": {"codename": "change_encodedvideo", "name": "Can change encoded video", "content_type": 139}}, {"pk": 420, "model": "auth.permission", "fields": {"codename": "delete_encodedvideo", "name": "Can delete encoded video", "content_type": 139}}, {"pk": 409, "model": "auth.permission", "fields": {"codename": "add_profile", "name": "Can add profile", "content_type": 136}}, {"pk": 410, "model": "auth.permission", "fields": {"codename": "change_profile", "name": "Can change profile", "content_type": 136}}, {"pk": 411, "model": "auth.permission", "fields": {"codename": "delete_profile", "name": "Can delete profile", "content_type": 136}}, {"pk": 421, "model": "auth.permission", "fields": {"codename": "add_subtitle", "name": "Can add subtitle", "content_type": 140}}, {"pk": 422, "model": "auth.permission", "fields": {"codename": "change_subtitle", "name": "Can change subtitle", "content_type": 140}}, {"pk": 423, "model": "auth.permission", "fields": {"codename": "delete_subtitle", "name": "Can delete subtitle", "content_type": 140}}, {"pk": 412, "model": "auth.permission", "fields": {"codename": "add_video", "name": "Can add video", "content_type": 137}}, {"pk": 413, "model": "auth.permission", "fields": {"codename": "change_video", "name": "Can change video", "content_type": 137}}, {"pk": 414, "model": "auth.permission", "fields": {"codename": "delete_video", "name": "Can delete video", "content_type": 137}}, {"pk": 316, "model": "auth.permission", "fields": {"codename": "add_embargoedcourse", "name": "Can add embargoed course", "content_type": 105}}, {"pk": 317, "model": "auth.permission", "fields": {"codename": "change_embargoedcourse", "name": "Can change embargoed course", "content_type": 105}}, {"pk": 318, "model": "auth.permission", "fields": {"codename": "delete_embargoedcourse", "name": "Can delete embargoed course", "content_type": 105}}, {"pk": 319, "model": "auth.permission", "fields": {"codename": "add_embargoedstate", "name": "Can add embargoed state", "content_type": 106}}, {"pk": 320, "model": "auth.permission", "fields": {"codename": "change_embargoedstate", "name": "Can change embargoed state", "content_type": 106}}, {"pk": 321, "model": "auth.permission", "fields": {"codename": "delete_embargoedstate", "name": "Can delete embargoed state", "content_type": 106}}, {"pk": 322, "model": "auth.permission", "fields": {"codename": "add_ipfilter", "name": "Can add ip filter", "content_type": 107}}, {"pk": 323, "model": "auth.permission", "fields": {"codename": "change_ipfilter", "name": "Can change ip filter", "content_type": 107}}, {"pk": 324, "model": "auth.permission", "fields": {"codename": "delete_ipfilter", "name": "Can delete ip filter", "content_type": 107}}, {"pk": 175, "model": "auth.permission", "fields": {"codename": "add_externalauthmap", "name": "Can add external auth map", "content_type": 59}}, {"pk": 176, "model": "auth.permission", "fields": {"codename": "change_externalauthmap", "name": "Can change external auth map", "content_type": 59}}, {"pk": 177, "model": "auth.permission", "fields": {"codename": "delete_externalauthmap", "name": "Can delete external auth map", "content_type": 59}}, {"pk": 241, "model": "auth.permission", "fields": {"codename": "add_puzzlecomplete", "name": "Can add puzzle complete", "content_type": 80}}, {"pk": 242, "model": "auth.permission", "fields": {"codename": "change_puzzlecomplete", "name": "Can change puzzle complete", "content_type": 80}}, {"pk": 243, "model": "auth.permission", "fields": {"codename": "delete_puzzlecomplete", "name": "Can delete puzzle complete", "content_type": 80}}, {"pk": 238, "model": "auth.permission", "fields": {"codename": "add_score", "name": "Can add score", "content_type": 79}}, {"pk": 239, "model": "auth.permission", "fields": {"codename": "change_score", "name": "Can change score", "content_type": 79}}, {"pk": 240, "model": "auth.permission", "fields": {"codename": "delete_score", "name": "Can delete score", "content_type": 79}}, {"pk": 148, "model": "auth.permission", "fields": {"codename": "add_instructortask", "name": "Can add instructor task", "content_type": 50}}, {"pk": 149, "model": "auth.permission", "fields": {"codename": "change_instructortask", "name": "Can change instructor task", "content_type": 50}}, {"pk": 150, "model": "auth.permission", "fields": {"codename": "delete_instructortask", "name": "Can delete instructor task", "content_type": 50}}, {"pk": 151, "model": "auth.permission", "fields": {"codename": "add_coursesoftware", "name": "Can add course software", "content_type": 51}}, {"pk": 152, "model": "auth.permission", "fields": {"codename": "change_coursesoftware", "name": "Can change course software", "content_type": 51}}, {"pk": 153, "model": "auth.permission", "fields": {"codename": "delete_coursesoftware", "name": "Can delete course software", "content_type": 51}}, {"pk": 154, "model": "auth.permission", "fields": {"codename": "add_userlicense", "name": "Can add user license", "content_type": 52}}, {"pk": 155, "model": "auth.permission", "fields": {"codename": "change_userlicense", "name": "Can change user license", "content_type": 52}}, {"pk": 156, "model": "auth.permission", "fields": {"codename": "delete_userlicense", "name": "Can delete user license", "content_type": 52}}, {"pk": 334, "model": "auth.permission", "fields": {"codename": "add_xblockasidesconfig", "name": "Can add x block asides config", "content_type": 111}}, {"pk": 335, "model": "auth.permission", "fields": {"codename": "change_xblockasidesconfig", "name": "Can change x block asides config", "content_type": 111}}, {"pk": 336, "model": "auth.permission", "fields": {"codename": "delete_xblockasidesconfig", "name": "Can delete x block asides config", "content_type": 111}}, {"pk": 337, "model": "auth.permission", "fields": {"codename": "add_answer", "name": "Can add answer", "content_type": 112}}, {"pk": 338, "model": "auth.permission", "fields": {"codename": "change_answer", "name": "Can change answer", "content_type": 112}}, {"pk": 339, "model": "auth.permission", "fields": {"codename": "delete_answer", "name": "Can delete answer", "content_type": 112}}, {"pk": 340, "model": "auth.permission", "fields": {"codename": "add_lightchild", "name": "Can add light child", "content_type": 113}}, {"pk": 341, "model": "auth.permission", "fields": {"codename": "change_lightchild", "name": "Can change light child", "content_type": 113}}, {"pk": 342, "model": "auth.permission", "fields": {"codename": "delete_lightchild", "name": "Can delete light child", "content_type": 113}}, {"pk": 433, "model": "auth.permission", "fields": {"codename": "add_coursecontentmilestone", "name": "Can add course content milestone", "content_type": 144}}, {"pk": 434, "model": "auth.permission", "fields": {"codename": "change_coursecontentmilestone", "name": "Can change course content milestone", "content_type": 144}}, {"pk": 435, "model": "auth.permission", "fields": {"codename": "delete_coursecontentmilestone", "name": "Can delete course content milestone", "content_type": 144}}, {"pk": 430, "model": "auth.permission", "fields": {"codename": "add_coursemilestone", "name": "Can add course milestone", "content_type": 143}}, {"pk": 431, "model": "auth.permission", "fields": {"codename": "change_coursemilestone", "name": "Can change course milestone", "content_type": 143}}, {"pk": 432, "model": "auth.permission", "fields": {"codename": "delete_coursemilestone", "name": "Can delete course milestone", "content_type": 143}}, {"pk": 424, "model": "auth.permission", "fields": {"codename": "add_milestone", "name": "Can add milestone", "content_type": 141}}, {"pk": 425, "model": "auth.permission", "fields": {"codename": "change_milestone", "name": "Can change milestone", "content_type": 141}}, {"pk": 426, "model": "auth.permission", "fields": {"codename": "delete_milestone", "name": "Can delete milestone", "content_type": 141}}, {"pk": 427, "model": "auth.permission", "fields": {"codename": "add_milestonerelationshiptype", "name": "Can add milestone relationship type", "content_type": 142}}, {"pk": 428, "model": "auth.permission", "fields": {"codename": "change_milestonerelationshiptype", "name": "Can change milestone relationship type", "content_type": 142}}, {"pk": 429, "model": "auth.permission", "fields": {"codename": "delete_milestonerelationshiptype", "name": "Can delete milestone relationship type", "content_type": 142}}, {"pk": 436, "model": "auth.permission", "fields": {"codename": "add_usermilestone", "name": "Can add user milestone", "content_type": 145}}, {"pk": 437, "model": "auth.permission", "fields": {"codename": "change_usermilestone", "name": "Can change user milestone", "content_type": 145}}, {"pk": 438, "model": "auth.permission", "fields": {"codename": "delete_usermilestone", "name": "Can delete user milestone", "content_type": 145}}, {"pk": 244, "model": "auth.permission", "fields": {"codename": "add_note", "name": "Can add note", "content_type": 81}}, {"pk": 245, "model": "auth.permission", "fields": {"codename": "change_note", "name": "Can change note", "content_type": 81}}, {"pk": 246, "model": "auth.permission", "fields": {"codename": "delete_note", "name": "Can delete note", "content_type": 81}}, {"pk": 184, "model": "auth.permission", "fields": {"codename": "add_accesstoken", "name": "Can add access token", "content_type": 62}}, {"pk": 185, "model": "auth.permission", "fields": {"codename": "change_accesstoken", "name": "Can change access token", "content_type": 62}}, {"pk": 186, "model": "auth.permission", "fields": {"codename": "delete_accesstoken", "name": "Can delete access token", "content_type": 62}}, {"pk": 178, "model": "auth.permission", "fields": {"codename": "add_client", "name": "Can add client", "content_type": 60}}, {"pk": 179, "model": "auth.permission", "fields": {"codename": "change_client", "name": "Can change client", "content_type": 60}}, {"pk": 180, "model": "auth.permission", "fields": {"codename": "delete_client", "name": "Can delete client", "content_type": 60}}, {"pk": 181, "model": "auth.permission", "fields": {"codename": "add_grant", "name": "Can add grant", "content_type": 61}}, {"pk": 182, "model": "auth.permission", "fields": {"codename": "change_grant", "name": "Can change grant", "content_type": 61}}, {"pk": 183, "model": "auth.permission", "fields": {"codename": "delete_grant", "name": "Can delete grant", "content_type": 61}}, {"pk": 187, "model": "auth.permission", "fields": {"codename": "add_refreshtoken", "name": "Can add refresh token", "content_type": 63}}, {"pk": 188, "model": "auth.permission", "fields": {"codename": "change_refreshtoken", "name": "Can change refresh token", "content_type": 63}}, {"pk": 189, "model": "auth.permission", "fields": {"codename": "delete_refreshtoken", "name": "Can delete refresh token", "content_type": 63}}, {"pk": 190, "model": "auth.permission", "fields": {"codename": "add_trustedclient", "name": "Can add trusted client", "content_type": 64}}, {"pk": 191, "model": "auth.permission", "fields": {"codename": "change_trustedclient", "name": "Can change trusted client", "content_type": 64}}, {"pk": 192, "model": "auth.permission", "fields": {"codename": "delete_trustedclient", "name": "Can delete trusted client", "content_type": 64}}, {"pk": 49, "model": "auth.permission", "fields": {"codename": "add_psychometricdata", "name": "Can add psychometric data", "content_type": 17}}, {"pk": 50, "model": "auth.permission", "fields": {"codename": "change_psychometricdata", "name": "Can change psychometric data", "content_type": 17}}, {"pk": 51, "model": "auth.permission", "fields": {"codename": "delete_psychometricdata", "name": "Can delete psychometric data", "content_type": 17}}, {"pk": 313, "model": "auth.permission", "fields": {"codename": "add_midcoursereverificationwindow", "name": "Can add midcourse reverification window", "content_type": 104}}, {"pk": 314, "model": "auth.permission", "fields": {"codename": "change_midcoursereverificationwindow", "name": "Can change midcourse reverification window", "content_type": 104}}, {"pk": 315, "model": "auth.permission", "fields": {"codename": "delete_midcoursereverificationwindow", "name": "Can delete midcourse reverification window", "content_type": 104}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 5}}, {"pk": 292, "model": "auth.permission", "fields": {"codename": "add_certificateitem", "name": "Can add certificate item", "content_type": 97}}, {"pk": 293, "model": "auth.permission", "fields": {"codename": "change_certificateitem", "name": "Can change certificate item", "content_type": 97}}, {"pk": 294, "model": "auth.permission", "fields": {"codename": "delete_certificateitem", "name": "Can delete certificate item", "content_type": 97}}, {"pk": 274, "model": "auth.permission", "fields": {"codename": "add_coupon", "name": "Can add coupon", "content_type": 91}}, {"pk": 275, "model": "auth.permission", "fields": {"codename": "change_coupon", "name": "Can change coupon", "content_type": 91}}, {"pk": 276, "model": "auth.permission", "fields": {"codename": "delete_coupon", "name": "Can delete coupon", "content_type": 91}}, {"pk": 277, "model": "auth.permission", "fields": {"codename": "add_couponredemption", "name": "Can add coupon redemption", "content_type": 92}}, {"pk": 278, "model": "auth.permission", "fields": {"codename": "change_couponredemption", "name": "Can change coupon redemption", "content_type": 92}}, {"pk": 279, "model": "auth.permission", "fields": {"codename": "delete_couponredemption", "name": "Can delete coupon redemption", "content_type": 92}}, {"pk": 283, "model": "auth.permission", "fields": {"codename": "add_courseregcodeitem", "name": "Can add course reg code item", "content_type": 94}}, {"pk": 284, "model": "auth.permission", "fields": {"codename": "change_courseregcodeitem", "name": "Can change course reg code item", "content_type": 94}}, {"pk": 285, "model": "auth.permission", "fields": {"codename": "delete_courseregcodeitem", "name": "Can delete course reg code item", "content_type": 94}}, {"pk": 286, "model": "auth.permission", "fields": {"codename": "add_courseregcodeitemannotation", "name": "Can add course reg code item annotation", "content_type": 95}}, {"pk": 287, "model": "auth.permission", "fields": {"codename": "change_courseregcodeitemannotation", "name": "Can change course reg code item annotation", "content_type": 95}}, {"pk": 288, "model": "auth.permission", "fields": {"codename": "delete_courseregcodeitemannotation", "name": "Can delete course reg code item annotation", "content_type": 95}}, {"pk": 268, "model": "auth.permission", "fields": {"codename": "add_courseregistrationcode", "name": "Can add course registration code", "content_type": 89}}, {"pk": 269, "model": "auth.permission", "fields": {"codename": "change_courseregistrationcode", "name": "Can change course registration code", "content_type": 89}}, {"pk": 270, "model": "auth.permission", "fields": {"codename": "delete_courseregistrationcode", "name": "Can delete course registration code", "content_type": 89}}, {"pk": 298, "model": "auth.permission", "fields": {"codename": "add_donation", "name": "Can add donation", "content_type": 99}}, {"pk": 299, "model": "auth.permission", "fields": {"codename": "change_donation", "name": "Can change donation", "content_type": 99}}, {"pk": 300, "model": "auth.permission", "fields": {"codename": "delete_donation", "name": "Can delete donation", "content_type": 99}}, {"pk": 295, "model": "auth.permission", "fields": {"codename": "add_donationconfiguration", "name": "Can add donation configuration", "content_type": 98}}, {"pk": 296, "model": "auth.permission", "fields": {"codename": "change_donationconfiguration", "name": "Can change donation configuration", "content_type": 98}}, {"pk": 297, "model": "auth.permission", "fields": {"codename": "delete_donationconfiguration", "name": "Can delete donation configuration", "content_type": 98}}, {"pk": 265, "model": "auth.permission", "fields": {"codename": "add_invoice", "name": "Can add invoice", "content_type": 88}}, {"pk": 266, "model": "auth.permission", "fields": {"codename": "change_invoice", "name": "Can change invoice", "content_type": 88}}, {"pk": 267, "model": "auth.permission", "fields": {"codename": "delete_invoice", "name": "Can delete invoice", "content_type": 88}}, {"pk": 259, "model": "auth.permission", "fields": {"codename": "add_order", "name": "Can add order", "content_type": 86}}, {"pk": 260, "model": "auth.permission", "fields": {"codename": "change_order", "name": "Can change order", "content_type": 86}}, {"pk": 261, "model": "auth.permission", "fields": {"codename": "delete_order", "name": "Can delete order", "content_type": 86}}, {"pk": 262, "model": "auth.permission", "fields": {"codename": "add_orderitem", "name": "Can add order item", "content_type": 87}}, {"pk": 263, "model": "auth.permission", "fields": {"codename": "change_orderitem", "name": "Can change order item", "content_type": 87}}, {"pk": 264, "model": "auth.permission", "fields": {"codename": "delete_orderitem", "name": "Can delete order item", "content_type": 87}}, {"pk": 280, "model": "auth.permission", "fields": {"codename": "add_paidcourseregistration", "name": "Can add paid course registration", "content_type": 93}}, {"pk": 281, "model": "auth.permission", "fields": {"codename": "change_paidcourseregistration", "name": "Can change paid course registration", "content_type": 93}}, {"pk": 282, "model": "auth.permission", "fields": {"codename": "delete_paidcourseregistration", "name": "Can delete paid course registration", "content_type": 93}}, {"pk": 289, "model": "auth.permission", "fields": {"codename": "add_paidcourseregistrationannotation", "name": "Can add paid course registration annotation", "content_type": 96}}, {"pk": 290, "model": "auth.permission", "fields": {"codename": "change_paidcourseregistrationannotation", "name": "Can change paid course registration annotation", "content_type": 96}}, {"pk": 291, "model": "auth.permission", "fields": {"codename": "delete_paidcourseregistrationannotation", "name": "Can delete paid course registration annotation", "content_type": 96}}, {"pk": 271, "model": "auth.permission", "fields": {"codename": "add_registrationcoderedemption", "name": "Can add registration code redemption", "content_type": 90}}, {"pk": 272, "model": "auth.permission", "fields": {"codename": "change_registrationcoderedemption", "name": "Can change registration code redemption", "content_type": 90}}, {"pk": 273, "model": "auth.permission", "fields": {"codename": "delete_registrationcoderedemption", "name": "Can delete registration code redemption", "content_type": 90}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 6}}, {"pk": 43, "model": "auth.permission", "fields": {"codename": "add_migrationhistory", "name": "Can add migration history", "content_type": 15}}, {"pk": 44, "model": "auth.permission", "fields": {"codename": "change_migrationhistory", "name": "Can change migration history", "content_type": 15}}, {"pk": 45, "model": "auth.permission", "fields": {"codename": "delete_migrationhistory", "name": "Can delete migration history", "content_type": 15}}, {"pk": 247, "model": "auth.permission", "fields": {"codename": "add_splashconfig", "name": "Can add splash config", "content_type": 82}}, {"pk": 248, "model": "auth.permission", "fields": {"codename": "change_splashconfig", "name": "Can change splash config", "content_type": 82}}, {"pk": 249, "model": "auth.permission", "fields": {"codename": "delete_splashconfig", "name": "Can delete splash config", "content_type": 82}}, {"pk": 97, "model": "auth.permission", "fields": {"codename": "add_anonymoususerid", "name": "Can add anonymous user id", "content_type": 33}}, {"pk": 98, "model": "auth.permission", "fields": {"codename": "change_anonymoususerid", "name": "Can change anonymous user id", "content_type": 33}}, {"pk": 99, "model": "auth.permission", "fields": {"codename": "delete_anonymoususerid", "name": "Can delete anonymous user id", "content_type": 33}}, {"pk": 133, "model": "auth.permission", "fields": {"codename": "add_courseaccessrole", "name": "Can add course access role", "content_type": 45}}, {"pk": 134, "model": "auth.permission", "fields": {"codename": "change_courseaccessrole", "name": "Can change course access role", "content_type": 45}}, {"pk": 135, "model": "auth.permission", "fields": {"codename": "delete_courseaccessrole", "name": "Can delete course access role", "content_type": 45}}, {"pk": 127, "model": "auth.permission", "fields": {"codename": "add_courseenrollment", "name": "Can add course enrollment", "content_type": 43}}, {"pk": 128, "model": "auth.permission", "fields": {"codename": "change_courseenrollment", "name": "Can change course enrollment", "content_type": 43}}, {"pk": 129, "model": "auth.permission", "fields": {"codename": "delete_courseenrollment", "name": "Can delete course enrollment", "content_type": 43}}, {"pk": 130, "model": "auth.permission", "fields": {"codename": "add_courseenrollmentallowed", "name": "Can add course enrollment allowed", "content_type": 44}}, {"pk": 131, "model": "auth.permission", "fields": {"codename": "change_courseenrollmentallowed", "name": "Can change course enrollment allowed", "content_type": 44}}, {"pk": 132, "model": "auth.permission", "fields": {"codename": "delete_courseenrollmentallowed", "name": "Can delete course enrollment allowed", "content_type": 44}}, {"pk": 136, "model": "auth.permission", "fields": {"codename": "add_dashboardconfiguration", "name": "Can add dashboard configuration", "content_type": 46}}, {"pk": 137, "model": "auth.permission", "fields": {"codename": "change_dashboardconfiguration", "name": "Can change dashboard configuration", "content_type": 46}}, {"pk": 138, "model": "auth.permission", "fields": {"codename": "delete_dashboardconfiguration", "name": "Can delete dashboard configuration", "content_type": 46}}, {"pk": 124, "model": "auth.permission", "fields": {"codename": "add_loginfailures", "name": "Can add login failures", "content_type": 42}}, {"pk": 125, "model": "auth.permission", "fields": {"codename": "change_loginfailures", "name": "Can change login failures", "content_type": 42}}, {"pk": 126, "model": "auth.permission", "fields": {"codename": "delete_loginfailures", "name": "Can delete login failures", "content_type": 42}}, {"pk": 121, "model": "auth.permission", "fields": {"codename": "add_passwordhistory", "name": "Can add password history", "content_type": 41}}, {"pk": 122, "model": "auth.permission", "fields": {"codename": "change_passwordhistory", "name": "Can change password history", "content_type": 41}}, {"pk": 123, "model": "auth.permission", "fields": {"codename": "delete_passwordhistory", "name": "Can delete password history", "content_type": 41}}, {"pk": 118, "model": "auth.permission", "fields": {"codename": "add_pendingemailchange", "name": "Can add pending email change", "content_type": 40}}, {"pk": 119, "model": "auth.permission", "fields": {"codename": "change_pendingemailchange", "name": "Can change pending email change", "content_type": 40}}, {"pk": 120, "model": "auth.permission", "fields": {"codename": "delete_pendingemailchange", "name": "Can delete pending email change", "content_type": 40}}, {"pk": 115, "model": "auth.permission", "fields": {"codename": "add_pendingnamechange", "name": "Can add pending name change", "content_type": 39}}, {"pk": 116, "model": "auth.permission", "fields": {"codename": "change_pendingnamechange", "name": "Can change pending name change", "content_type": 39}}, {"pk": 117, "model": "auth.permission", "fields": {"codename": "delete_pendingnamechange", "name": "Can delete pending name change", "content_type": 39}}, {"pk": 112, "model": "auth.permission", "fields": {"codename": "add_registration", "name": "Can add registration", "content_type": 38}}, {"pk": 113, "model": "auth.permission", "fields": {"codename": "change_registration", "name": "Can change registration", "content_type": 38}}, {"pk": 114, "model": "auth.permission", "fields": {"codename": "delete_registration", "name": "Can delete registration", "content_type": 38}}, {"pk": 103, "model": "auth.permission", "fields": {"codename": "add_userprofile", "name": "Can add user profile", "content_type": 35}}, {"pk": 104, "model": "auth.permission", "fields": {"codename": "change_userprofile", "name": "Can change user profile", "content_type": 35}}, {"pk": 105, "model": "auth.permission", "fields": {"codename": "delete_userprofile", "name": "Can delete user profile", "content_type": 35}}, {"pk": 106, "model": "auth.permission", "fields": {"codename": "add_usersignupsource", "name": "Can add user signup source", "content_type": 36}}, {"pk": 107, "model": "auth.permission", "fields": {"codename": "change_usersignupsource", "name": "Can change user signup source", "content_type": 36}}, {"pk": 108, "model": "auth.permission", "fields": {"codename": "delete_usersignupsource", "name": "Can delete user signup source", "content_type": 36}}, {"pk": 100, "model": "auth.permission", "fields": {"codename": "add_userstanding", "name": "Can add user standing", "content_type": 34}}, {"pk": 101, "model": "auth.permission", "fields": {"codename": "change_userstanding", "name": "Can change user standing", "content_type": 34}}, {"pk": 102, "model": "auth.permission", "fields": {"codename": "delete_userstanding", "name": "Can delete user standing", "content_type": 34}}, {"pk": 109, "model": "auth.permission", "fields": {"codename": "add_usertestgroup", "name": "Can add user test group", "content_type": 37}}, {"pk": 110, "model": "auth.permission", "fields": {"codename": "change_usertestgroup", "name": "Can change user test group", "content_type": 37}}, {"pk": 111, "model": "auth.permission", "fields": {"codename": "delete_usertestgroup", "name": "Can delete user test group", "content_type": 37}}, {"pk": 349, "model": "auth.permission", "fields": {"codename": "add_score", "name": "Can add score", "content_type": 116}}, {"pk": 350, "model": "auth.permission", "fields": {"codename": "change_score", "name": "Can change score", "content_type": 116}}, {"pk": 351, "model": "auth.permission", "fields": {"codename": "delete_score", "name": "Can delete score", "content_type": 116}}, {"pk": 352, "model": "auth.permission", "fields": {"codename": "add_scoresummary", "name": "Can add score summary", "content_type": 117}}, {"pk": 353, "model": "auth.permission", "fields": {"codename": "change_scoresummary", "name": "Can change score summary", "content_type": 117}}, {"pk": 354, "model": "auth.permission", "fields": {"codename": "delete_scoresummary", "name": "Can delete score summary", "content_type": 117}}, {"pk": 343, "model": "auth.permission", "fields": {"codename": "add_studentitem", "name": "Can add student item", "content_type": 114}}, {"pk": 344, "model": "auth.permission", "fields": {"codename": "change_studentitem", "name": "Can change student item", "content_type": 114}}, {"pk": 345, "model": "auth.permission", "fields": {"codename": "delete_studentitem", "name": "Can delete student item", "content_type": 114}}, {"pk": 346, "model": "auth.permission", "fields": {"codename": "add_submission", "name": "Can add submission", "content_type": 115}}, {"pk": 347, "model": "auth.permission", "fields": {"codename": "change_submission", "name": "Can change submission", "content_type": 115}}, {"pk": 348, "model": "auth.permission", "fields": {"codename": "delete_submission", "name": "Can delete submission", "content_type": 115}}, {"pk": 331, "model": "auth.permission", "fields": {"codename": "add_surveyanswer", "name": "Can add survey answer", "content_type": 110}}, {"pk": 332, "model": "auth.permission", "fields": {"codename": "change_surveyanswer", "name": "Can change survey answer", "content_type": 110}}, {"pk": 333, "model": "auth.permission", "fields": {"codename": "delete_surveyanswer", "name": "Can delete survey answer", "content_type": 110}}, {"pk": 328, "model": "auth.permission", "fields": {"codename": "add_surveyform", "name": "Can add survey form", "content_type": 109}}, {"pk": 329, "model": "auth.permission", "fields": {"codename": "change_surveyform", "name": "Can change survey form", "content_type": 109}}, {"pk": 330, "model": "auth.permission", "fields": {"codename": "delete_surveyform", "name": "Can delete survey form", "content_type": 109}}, {"pk": 139, "model": "auth.permission", "fields": {"codename": "add_trackinglog", "name": "Can add tracking log", "content_type": 47}}, {"pk": 140, "model": "auth.permission", "fields": {"codename": "change_trackinglog", "name": "Can change tracking log", "content_type": 47}}, {"pk": 141, "model": "auth.permission", "fields": {"codename": "delete_trackinglog", "name": "Can delete tracking log", "content_type": 47}}, {"pk": 253, "model": "auth.permission", "fields": {"codename": "add_usercoursetag", "name": "Can add user course tag", "content_type": 84}}, {"pk": 254, "model": "auth.permission", "fields": {"codename": "change_usercoursetag", "name": "Can change user course tag", "content_type": 84}}, {"pk": 255, "model": "auth.permission", "fields": {"codename": "delete_usercoursetag", "name": "Can delete user course tag", "content_type": 84}}, {"pk": 256, "model": "auth.permission", "fields": {"codename": "add_userorgtag", "name": "Can add user org tag", "content_type": 85}}, {"pk": 257, "model": "auth.permission", "fields": {"codename": "change_userorgtag", "name": "Can change user org tag", "content_type": 85}}, {"pk": 258, "model": "auth.permission", "fields": {"codename": "delete_userorgtag", "name": "Can delete user org tag", "content_type": 85}}, {"pk": 250, "model": "auth.permission", "fields": {"codename": "add_userpreference", "name": "Can add user preference", "content_type": 83}}, {"pk": 251, "model": "auth.permission", "fields": {"codename": "change_userpreference", "name": "Can change user preference", "content_type": 83}}, {"pk": 252, "model": "auth.permission", "fields": {"codename": "delete_userpreference", "name": "Can delete user preference", "content_type": 83}}, {"pk": 307, "model": "auth.permission", "fields": {"codename": "add_softwaresecurephotoverification", "name": "Can add software secure photo verification", "content_type": 102}}, {"pk": 308, "model": "auth.permission", "fields": {"codename": "change_softwaresecurephotoverification", "name": "Can change software secure photo verification", "content_type": 102}}, {"pk": 309, "model": "auth.permission", "fields": {"codename": "delete_softwaresecurephotoverification", "name": "Can delete software secure photo verification", "content_type": 102}}, {"pk": 193, "model": "auth.permission", "fields": {"codename": "add_article", "name": "Can add article", "content_type": 65}}, {"pk": 197, "model": "auth.permission", "fields": {"codename": "assign", "name": "Can change ownership of any article", "content_type": 65}}, {"pk": 194, "model": "auth.permission", "fields": {"codename": "change_article", "name": "Can change article", "content_type": 65}}, {"pk": 195, "model": "auth.permission", "fields": {"codename": "delete_article", "name": "Can delete article", "content_type": 65}}, {"pk": 198, "model": "auth.permission", "fields": {"codename": "grant", "name": "Can assign permissions to other users", "content_type": 65}}, {"pk": 196, "model": "auth.permission", "fields": {"codename": "moderate", "name": "Can edit all articles and lock/unlock/restore", "content_type": 65}}, {"pk": 199, "model": "auth.permission", "fields": {"codename": "add_articleforobject", "name": "Can add Article for object", "content_type": 66}}, {"pk": 200, "model": "auth.permission", "fields": {"codename": "change_articleforobject", "name": "Can change Article for object", "content_type": 66}}, {"pk": 201, "model": "auth.permission", "fields": {"codename": "delete_articleforobject", "name": "Can delete Article for object", "content_type": 66}}, {"pk": 208, "model": "auth.permission", "fields": {"codename": "add_articleplugin", "name": "Can add article plugin", "content_type": 69}}, {"pk": 209, "model": "auth.permission", "fields": {"codename": "change_articleplugin", "name": "Can change article plugin", "content_type": 69}}, {"pk": 210, "model": "auth.permission", "fields": {"codename": "delete_articleplugin", "name": "Can delete article plugin", "content_type": 69}}, {"pk": 202, "model": "auth.permission", "fields": {"codename": "add_articlerevision", "name": "Can add article revision", "content_type": 67}}, {"pk": 203, "model": "auth.permission", "fields": {"codename": "change_articlerevision", "name": "Can change article revision", "content_type": 67}}, {"pk": 204, "model": "auth.permission", "fields": {"codename": "delete_articlerevision", "name": "Can delete article revision", "content_type": 67}}, {"pk": 223, "model": "auth.permission", "fields": {"codename": "add_articlesubscription", "name": "Can add article subscription", "content_type": 74}}, {"pk": 224, "model": "auth.permission", "fields": {"codename": "change_articlesubscription", "name": "Can change article subscription", "content_type": 74}}, {"pk": 225, "model": "auth.permission", "fields": {"codename": "delete_articlesubscription", "name": "Can delete article subscription", "content_type": 74}}, {"pk": 211, "model": "auth.permission", "fields": {"codename": "add_reusableplugin", "name": "Can add reusable plugin", "content_type": 70}}, {"pk": 212, "model": "auth.permission", "fields": {"codename": "change_reusableplugin", "name": "Can change reusable plugin", "content_type": 70}}, {"pk": 213, "model": "auth.permission", "fields": {"codename": "delete_reusableplugin", "name": "Can delete reusable plugin", "content_type": 70}}, {"pk": 217, "model": "auth.permission", "fields": {"codename": "add_revisionplugin", "name": "Can add revision plugin", "content_type": 72}}, {"pk": 218, "model": "auth.permission", "fields": {"codename": "change_revisionplugin", "name": "Can change revision plugin", "content_type": 72}}, {"pk": 219, "model": "auth.permission", "fields": {"codename": "delete_revisionplugin", "name": "Can delete revision plugin", "content_type": 72}}, {"pk": 220, "model": "auth.permission", "fields": {"codename": "add_revisionpluginrevision", "name": "Can add revision plugin revision", "content_type": 73}}, {"pk": 221, "model": "auth.permission", "fields": {"codename": "change_revisionpluginrevision", "name": "Can change revision plugin revision", "content_type": 73}}, {"pk": 222, "model": "auth.permission", "fields": {"codename": "delete_revisionpluginrevision", "name": "Can delete revision plugin revision", "content_type": 73}}, {"pk": 214, "model": "auth.permission", "fields": {"codename": "add_simpleplugin", "name": "Can add simple plugin", "content_type": 71}}, {"pk": 215, "model": "auth.permission", "fields": {"codename": "change_simpleplugin", "name": "Can change simple plugin", "content_type": 71}}, {"pk": 216, "model": "auth.permission", "fields": {"codename": "delete_simpleplugin", "name": "Can delete simple plugin", "content_type": 71}}, {"pk": 205, "model": "auth.permission", "fields": {"codename": "add_urlpath", "name": "Can add URL path", "content_type": 68}}, {"pk": 206, "model": "auth.permission", "fields": {"codename": "change_urlpath", "name": "Can change URL path", "content_type": 68}}, {"pk": 207, "model": "auth.permission", "fields": {"codename": "delete_urlpath", "name": "Can delete URL path", "content_type": 68}}, {"pk": 403, "model": "auth.permission", "fields": {"codename": "add_assessmentworkflow", "name": "Can add assessment workflow", "content_type": 134}}, {"pk": 404, "model": "auth.permission", "fields": {"codename": "change_assessmentworkflow", "name": "Can change assessment workflow", "content_type": 134}}, {"pk": 405, "model": "auth.permission", "fields": {"codename": "delete_assessmentworkflow", "name": "Can delete assessment workflow", "content_type": 134}}, {"pk": 406, "model": "auth.permission", "fields": {"codename": "add_assessmentworkflowstep", "name": "Can add assessment workflow step", "content_type": 135}}, {"pk": 407, "model": "auth.permission", "fields": {"codename": "change_assessmentworkflowstep", "name": "Can change assessment workflow step", "content_type": 135}}, {"pk": 408, "model": "auth.permission", "fields": {"codename": "delete_assessmentworkflowstep", "name": "Can delete assessment workflow step", "content_type": 135}}, {"pk": 445, "model": "auth.permission", "fields": {"codename": "add_studioconfig", "name": "Can add studio config", "content_type": 148}}, {"pk": 446, "model": "auth.permission", "fields": {"codename": "change_studioconfig", "name": "Can change studio config", "content_type": 148}}, {"pk": 447, "model": "auth.permission", "fields": {"codename": "delete_studioconfig", "name": "Can delete studio config", "content_type": 148}}, {"pk": 1, "model": "dark_lang.darklangconfig", "fields": {"change_date": "2015-01-15T03:15:35Z", "changed_by": null, "enabled": true, "released_languages": ""}}]
diff --git a/common/test/db_cache/bok_choy_schema.sql b/common/test/db_cache/bok_choy_schema.sql
index 80b3c25e00..1fb4b60980 100644
--- a/common/test/db_cache/bok_choy_schema.sql
+++ b/common/test/db_cache/bok_choy_schema.sql
@@ -1102,8 +1102,8 @@ CREATE TABLE `djcelery_periodictask` (
UNIQUE KEY `name` (`name`),
KEY `djcelery_periodictask_17d2d99d` (`interval_id`),
KEY `djcelery_periodictask_7aa5fda` (`crontab_id`),
- CONSTRAINT `crontab_id_refs_id_ebff5e74` FOREIGN KEY (`crontab_id`) REFERENCES `djcelery_crontabschedule` (`id`),
- CONSTRAINT `interval_id_refs_id_f2054349` FOREIGN KEY (`interval_id`) REFERENCES `djcelery_intervalschedule` (`id`)
+ CONSTRAINT `interval_id_refs_id_f2054349` FOREIGN KEY (`interval_id`) REFERENCES `djcelery_intervalschedule` (`id`),
+ CONSTRAINT `crontab_id_refs_id_ebff5e74` FOREIGN KEY (`crontab_id`) REFERENCES `djcelery_crontabschedule` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `djcelery_periodictasks`;
diff --git a/lms/djangoapps/courseware/grades.py b/lms/djangoapps/courseware/grades.py
index 41169966e3..e100916fbd 100644
--- a/lms/djangoapps/courseware/grades.py
+++ b/lms/djangoapps/courseware/grades.py
@@ -22,35 +22,14 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.util.duedate import get_extended_due_date
from .models import StudentModule
from .module_render import get_module_for_descriptor
+from .module_utils import yield_dynamic_descriptor_descendents
from submissions import api as sub_api # installed from the edx-submissions repository
from opaque_keys import InvalidKeyError
+
log = logging.getLogger("edx.courseware")
-def yield_dynamic_descriptor_descendents(descriptor, module_creator):
- """
- This returns all of the descendants of a descriptor. If the descriptor
- has dynamic children, the module will be created using module_creator
- and the children (as descriptors) of that module will be returned.
- """
- def get_dynamic_descriptor_children(descriptor):
- if descriptor.has_dynamic_children():
- module = module_creator(descriptor)
- if module is None:
- return []
- return module.get_child_descriptors()
- else:
- return descriptor.get_children()
-
- stack = [descriptor]
-
- while len(stack) > 0:
- next_descriptor = stack.pop()
- stack.extend(get_dynamic_descriptor_children(next_descriptor))
- yield next_descriptor
-
-
def answer_distributions(course_key):
"""
Given a course_key, return answer distributions in the form of a dictionary
diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py
index 3d2d6daf53..fc4d9603e9 100644
--- a/lms/djangoapps/courseware/module_render.py
+++ b/lms/djangoapps/courseware/module_render.py
@@ -21,9 +21,11 @@ from capa.xqueue_interface import XQueueInterface
from courseware.access import has_access, get_user_role
from courseware.masquerade import setup_masquerade
from courseware.model_data import FieldDataCache, DjangoKeyValueStore
+from courseware.models import StudentModule
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem, unquote_slashes, quote_slashes
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
+from .module_utils import yield_dynamic_descriptor_descendents
from edxmako.shortcuts import render_to_string
from eventtracking import tracker
from psychometrics.psychoanalyze import make_psychometrics_data_update_handler
@@ -35,6 +37,7 @@ from xblock.exceptions import NoSuchHandlerError
from xblock.django.request import django_to_webob_request, webob_to_django_response
from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor
from xmodule.exceptions import NotFoundError, ProcessingError
+from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.django import modulestore, ModuleI18nService
@@ -53,7 +56,10 @@ from xmodule.x_module import XModuleDescriptor
from util.json_request import JsonResponse
from util.sandboxing import can_execute_unsafe_code, get_python_lib_zip
-
+if settings.FEATURES.get('MILESTONES_APP', False):
+ from milestones import api as milestones_api
+ from milestones.exceptions import InvalidMilestoneRelationshipTypeException
+ from util.milestones_helpers import serialize_user
log = logging.getLogger(__name__)
@@ -93,6 +99,31 @@ def make_track_function(request):
return function
+def _get_required_content(course, user):
+ """
+ Queries milestones subsystem to see if the specified course is gated on one or more milestones,
+ and if those milestones can be fulfilled via completion of a particular course content module
+ """
+ required_content = []
+ if settings.FEATURES.get('MILESTONES_APP', False):
+ # Get all of the outstanding milestones for this course, for this user
+ try:
+ milestone_paths = milestones_api.get_course_milestones_fulfillment_paths(
+ unicode(course.id),
+ serialize_user(user)
+ )
+ except InvalidMilestoneRelationshipTypeException:
+ return required_content
+
+ # For each outstanding milestone, see if this content is one of its fulfillment paths
+ for path_key in milestone_paths:
+ milestone_path = milestone_paths[path_key]
+ if milestone_path.get('content') and len(milestone_path['content']):
+ for content in milestone_path['content']:
+ required_content.append(content)
+ return required_content
+
+
def toc_for_course(request, course, active_chapter, active_section, field_data_cache):
'''
Create a table of contents from the module store
@@ -122,9 +153,20 @@ def toc_for_course(request, course, active_chapter, active_section, field_data_c
if course_module is None:
return None
+ # Check to see if the course is gated on required content (such as an Entrance Exam)
+ required_content = _get_required_content(course, request.user)
+
chapters = list()
for chapter in course_module.get_display_items():
- if chapter.hide_from_toc:
+ # Only show required content, if there is required content
+ # chapter.hide_from_toc is read-only (boo)
+ local_hide_from_toc = False
+ if len(required_content):
+ if unicode(chapter.location) not in required_content:
+ local_hide_from_toc = True
+
+ # Skip the current chapter if a hide flag is tripped
+ if chapter.hide_from_toc or local_hide_from_toc:
continue
sections = list()
@@ -141,7 +183,6 @@ def toc_for_course(request, course, active_chapter, active_section, field_data_c
'active': active,
'graded': section.graded,
})
-
chapters.append({'display_name': chapter.display_name_with_default,
'url_name': chapter.url_name,
'sections': sections,
@@ -341,7 +382,58 @@ def get_module_system_for_user(user, field_data_cache,
request_token=request_token,
)
- def handle_grade_event(block, event_type, event):
+ def _fulfill_content_milestones(course_key, content_key, user_id): # pylint: disable=unused-argument
+ """
+ Internal helper to handle milestone fulfillments for the specified content module
+ """
+ # Fulfillment Use Case: Entrance Exam
+ # If this module is part of an entrance exam, we'll need to see if the student
+ # has reached the point at which they can collect the associated milestone
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ course = modulestore().get_course(course_key)
+ content = modulestore().get_item(content_key)
+ entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False)
+ in_entrance_exam = getattr(content, 'in_entrance_exam', False)
+ if entrance_exam_enabled and in_entrance_exam:
+ exam_key = UsageKey.from_string(course.entrance_exam_id)
+ exam_descriptor = modulestore().get_item(exam_key)
+ exam_modules = yield_dynamic_descriptor_descendents(
+ exam_descriptor,
+ inner_get_module
+ )
+ ignore_categories = ['course', 'chapter', 'sequential', 'vertical']
+ module_pcts = []
+ exam_pct = 0
+ for module in exam_modules:
+ if module.graded and module.category not in ignore_categories:
+ module_pct = 0
+ try:
+ student_module = StudentModule.objects.get(
+ module_state_key=module.scope_ids.usage_id,
+ student_id=user_id
+ )
+ if student_module.max_grade:
+ module_pct = student_module.grade / student_module.max_grade
+ except StudentModule.DoesNotExist:
+ pass
+ module_pcts.append(module_pct)
+ exam_pct = sum(module_pcts) / float(len(module_pcts))
+ if exam_pct >= course.entrance_exam_minimum_score_pct:
+ relationship_types = milestones_api.get_milestone_relationship_types()
+ content_milestones = milestones_api.get_course_content_milestones(
+ course_key,
+ exam_key,
+ relationship=relationship_types['FULFILLS']
+ )
+ # Add each milestone to the user's set...
+ user = {'id': user_id}
+ for milestone in content_milestones:
+ milestones_api.add_user_milestone(user, milestone)
+
+ def handle_grade_event(block, event_type, event): # pylint: disable=unused-argument
+ """
+ Manages the workflow for recording and updating of student module grade state
+ """
user_id = event.get('user_id', user.id)
# Construct the key for the module
@@ -373,6 +465,16 @@ def get_module_system_for_user(user, field_data_cache,
dog_stats_api.increment("lms.courseware.question_answered", tags=tags)
+ # If we're using the awesome edx-milestones app, we need to cycle
+ # through the fulfillment scenarios to see if any are now applicable
+ # thanks to the updated grading information that was just submitted
+ if settings.FEATURES.get('MILESTONES_APP', False):
+ _fulfill_content_milestones(
+ course_id,
+ descriptor.location,
+ user_id
+ )
+
def publish(block, event_type, event):
"""A function that allows XModules to publish events."""
if event_type == 'grade':
diff --git a/lms/djangoapps/courseware/module_utils.py b/lms/djangoapps/courseware/module_utils.py
new file mode 100644
index 0000000000..017f879b1d
--- /dev/null
+++ b/lms/djangoapps/courseware/module_utils.py
@@ -0,0 +1,30 @@
+"""
+Utility library containing operations used/shared by multiple courseware modules
+"""
+
+
+def yield_dynamic_descriptor_descendents(descriptor, module_creator): # pylint: disable=invalid-name
+ """
+ This returns all of the descendants of a descriptor. If the descriptor
+ has dynamic children, the module will be created using module_creator
+ and the children (as descriptors) of that module will be returned.
+ """
+ def get_dynamic_descriptor_children(descriptor):
+ """
+ Internal recursive helper for traversing the child hierarchy
+ """
+ module_children = []
+ if descriptor.has_dynamic_children():
+ module = module_creator(descriptor)
+ if module is not None:
+ module_children = module.get_child_descriptors()
+ else:
+ module_children = descriptor.get_children()
+ return module_children
+
+ stack = [descriptor]
+
+ while len(stack) > 0:
+ next_descriptor = stack.pop()
+ stack.extend(get_dynamic_descriptor_children(next_descriptor))
+ yield next_descriptor
diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py
new file mode 100644
index 0000000000..1ba9e153c6
--- /dev/null
+++ b/lms/djangoapps/courseware/tabs.py
@@ -0,0 +1,59 @@
+"""
+This module is essentially a broker to xmodule/tabs.py -- it was originally introduced to
+perform some LMS-specific tab display gymnastics for the Entrance Exams feature
+"""
+from django.conf import settings
+from django.utils.translation import ugettext as _
+
+from courseware.access import has_access
+from student.models import CourseEnrollment
+from xmodule.tabs import CourseTabList
+
+if settings.FEATURES.get('MILESTONES_APP', False):
+ from milestones.api import get_course_milestones_fulfillment_paths
+ from util.milestones_helpers import serialize_user
+
+
+def get_course_tab_list(course, user):
+ """
+ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary
+ """
+ user_is_enrolled = user.is_authenticated() and CourseEnrollment.is_enrolled(user, course.id)
+ xmodule_tab_list = CourseTabList.iterate_displayable(
+ course,
+ settings,
+ user.is_authenticated(),
+ has_access(user, 'staff', course, course.id),
+ user_is_enrolled
+ )
+
+ # Entrance Exams Feature
+ # If the course has an entrance exam, we'll need to see if the user has not passed it
+ # If so, we'll need to hide away all of the tabs except for Courseware and Instructor
+ entrance_exam_mode = False
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+ if getattr(course, 'entrance_exam_enabled', False):
+ course_milestones_paths = get_course_milestones_fulfillment_paths(
+ unicode(course.id),
+ serialize_user(user)
+ )
+ for __, value in course_milestones_paths.iteritems():
+ if len(value.get('content', [])):
+ for content in value['content']:
+ if content == course.entrance_exam_id:
+ entrance_exam_mode = True
+ break
+
+ # Now that we've loaded the tabs for this course, perform the Entrance Exam mode work
+ # Majority case is no entrance exam defined
+ course_tab_list = []
+ for tab in xmodule_tab_list:
+ if entrance_exam_mode:
+ # Hide all of the tabs except for 'Courseware' and 'Instructor'
+ # Rename 'Courseware' tab to 'Entrance Exam'
+ if tab.type not in ['courseware', 'instructor']:
+ continue
+ if tab.type == 'courseware':
+ tab.name = _("Entrance Exam")
+ course_tab_list.append(tab)
+ return course_tab_list
diff --git a/lms/djangoapps/courseware/tests/test_entrance_exam.py b/lms/djangoapps/courseware/tests/test_entrance_exam.py
new file mode 100644
index 0000000000..7a81e01543
--- /dev/null
+++ b/lms/djangoapps/courseware/tests/test_entrance_exam.py
@@ -0,0 +1,276 @@
+"""
+Tests use cases related to LMS Entrance Exam behavior, such as gated content access (TOC)
+"""
+from django.test.client import RequestFactory
+from django.test.utils import override_settings
+
+from courseware.model_data import FieldDataCache
+from courseware.module_render import get_module, toc_for_course
+from courseware.tests.factories import UserFactory
+from milestones import api as milestones_api
+from milestones.models import MilestoneRelationshipType
+from xmodule.modulestore.django import modulestore
+from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MOCK_MODULESTORE
+from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
+from util.milestones_helpers import generate_milestone_namespace, NAMESPACE_CHOICES
+
+
+@override_settings(MODULESTORE=TEST_DATA_MOCK_MODULESTORE)
+class EntranceExamTestCases(ModuleStoreTestCase):
+ """
+ Check that content is properly gated. Create a test course from scratch to mess with.
+ """
+
+ def setUp(self):
+ """
+ Test case scaffolding
+ """
+ super(EntranceExamTestCases, self).setUp()
+ self.course = CourseFactory.create(
+ metadata={
+ 'entrance_exam_enabled': True,
+ }
+ )
+ chapter = ItemFactory.create(
+ parent=self.course,
+ display_name='Overview'
+ )
+ ItemFactory.create(
+ parent=chapter,
+ display_name='Welcome'
+ )
+ ItemFactory.create(
+ parent=self.course,
+ category='chapter',
+ display_name="Week 1"
+ )
+ ItemFactory.create(
+ parent=chapter,
+ category='sequential',
+ display_name="Lesson 1"
+ )
+ ItemFactory.create(
+ category="instructor",
+ parent=self.course,
+ data="Instructor Tab",
+ display_name="Instructor"
+ )
+ self.entrance_exam = ItemFactory.create(
+ parent=self.course,
+ category="chapter",
+ display_name="Entrance Exam Section - Chapter 1"
+ )
+ self.exam_1 = ItemFactory.create(
+ parent=self.entrance_exam,
+ category='sequential',
+ display_name="Exam Sequential - Subsection 1",
+ graded=True,
+ metadata={'in_entrance_exam': True}
+ )
+ subsection = ItemFactory.create(
+ parent=self.exam_1,
+ category='vertical',
+ display_name='Exam Vertical - Unit 1'
+ )
+ self.problem_1 = ItemFactory.create(
+ parent=subsection,
+ category="problem",
+ display_name="Exam Problem - Problem 1"
+ )
+ self.problem_2 = ItemFactory.create(
+ parent=subsection,
+ category="problem",
+ display_name="Exam Problem - Problem 2"
+ )
+ self.problem_3 = ItemFactory.create(
+ parent=subsection,
+ category="problem",
+ display_name="Exam Problem - Problem 3"
+ )
+ milestone_namespace = generate_milestone_namespace(
+ NAMESPACE_CHOICES['ENTRANCE_EXAM'],
+ self.course.id
+ )
+ self.milestone = {
+ 'name': 'Test Milestone',
+ 'namespace': milestone_namespace,
+ 'description': 'Testing Courseware Entrance Exam Chapter',
+ }
+ MilestoneRelationshipType.objects.create(name='requires', active=True)
+ MilestoneRelationshipType.objects.create(name='fulfills', active=True)
+ self.milestone_relationship_types = milestones_api.get_milestone_relationship_types()
+ self.milestone = milestones_api.add_milestone(self.milestone)
+ milestones_api.add_course_milestone(
+ unicode(self.course.id),
+ self.milestone_relationship_types['REQUIRES'],
+ self.milestone
+ )
+ milestones_api.add_course_content_milestone(
+ unicode(self.course.id),
+ unicode(self.entrance_exam.location),
+ self.milestone_relationship_types['FULFILLS'],
+ self.milestone
+ )
+ user = UserFactory()
+ self.request = RequestFactory()
+ self.request.user = user
+ self.request.COOKIES = {}
+ self.request.META = {}
+ self.request.is_secure = lambda: True
+ self.request.get_host = lambda: "edx.org"
+ self.request.method = 'GET'
+ self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
+ self.course.id,
+ user,
+ self.entrance_exam
+ )
+ self.entrance_exam.is_entrance_exam = True
+ self.entrance_exam.in_entrance_exam = True
+ self.course.entrance_exam_enabled = True
+ self.course.entrance_exam_minimum_score_pct = 0.50
+ self.course.entrance_exam_id = unicode(self.entrance_exam.scope_ids.usage_id)
+ modulestore().update_item(self.course, user.id) # pylint: disable=no-member
+
+ def test_entrance_exam_gating(self):
+ """
+ Unit Test: test_entrance_exam_gating
+ """
+ # This user helps to cover a discovered bug in the milestone fulfillment logic
+ chaos_user = UserFactory()
+ expected_locked_toc = (
+ [
+ {
+ 'active': True,
+ 'sections': [
+ {
+ 'url_name': u'Exam_Sequential_-_Subsection_1',
+ 'display_name': u'Exam Sequential - Subsection 1',
+ 'graded': True,
+ 'format': '',
+ 'due': None,
+ 'active': True
+ }
+ ],
+ 'url_name': u'Entrance_Exam_Section_-_Chapter_1',
+ 'display_name': u'Entrance Exam Section - Chapter 1'
+ }
+ ]
+ )
+ locked_toc = toc_for_course(
+ self.request,
+ self.course,
+ self.entrance_exam.url_name,
+ self.exam_1.url_name,
+ self.field_data_cache
+ )
+ for toc_section in expected_locked_toc:
+ self.assertIn(toc_section, locked_toc)
+
+ # Set up the chaos user
+ # pylint: disable=maybe-no-member,no-member
+ grade_dict = {'value': 1, 'max_value': 1, 'user_id': chaos_user.id}
+ field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
+ self.course.id,
+ chaos_user,
+ self.course,
+ depth=2
+ )
+ # pylint: disable=protected-access
+ module = get_module(
+ chaos_user,
+ self.request,
+ self.problem_1.scope_ids.usage_id,
+ field_data_cache,
+ )._xmodule
+ module.system.publish(self.problem_1, 'grade', grade_dict)
+
+ # pylint: disable=maybe-no-member,no-member
+ grade_dict = {'value': 1, 'max_value': 1, 'user_id': self.request.user.id}
+ field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
+ self.course.id,
+ self.request.user,
+ self.course,
+ depth=2
+ )
+ # pylint: disable=protected-access
+ module = get_module(
+ self.request.user,
+ self.request,
+ self.problem_1.scope_ids.usage_id,
+ field_data_cache,
+ )._xmodule
+ module.system.publish(self.problem_1, 'grade', grade_dict)
+
+ module = get_module(
+ self.request.user,
+ self.request,
+ self.problem_2.scope_ids.usage_id,
+ field_data_cache,
+ )._xmodule # pylint: disable=protected-access
+ module.system.publish(self.problem_2, 'grade', grade_dict)
+
+ expected_unlocked_toc = (
+ [
+ {
+ 'active': False,
+ 'sections': [
+ {
+ 'url_name': u'Welcome',
+ 'display_name': u'Welcome',
+ 'graded': False,
+ 'format': '',
+ 'due': None,
+ 'active': False
+ },
+ {
+ 'url_name': u'Lesson_1',
+ 'display_name': u'Lesson 1',
+ 'graded': False,
+ 'format': '',
+ 'due': None,
+ 'active': False
+ }
+ ],
+ 'url_name': u'Overview',
+ 'display_name': u'Overview'
+ },
+ {
+ 'active': False,
+ 'sections': [],
+ 'url_name': u'Week_1',
+ 'display_name': u'Week 1'
+ },
+ {
+ 'active': False,
+ 'sections': [],
+ 'url_name': u'Instructor',
+ 'display_name': u'Instructor'
+ },
+ {
+ 'active': True,
+ 'sections': [
+ {
+ 'url_name': u'Exam_Sequential_-_Subsection_1',
+ 'display_name': u'Exam Sequential - Subsection 1',
+ 'graded': True,
+ 'format': '',
+ 'due': None,
+ 'active': True
+ }
+ ],
+ 'url_name': u'Entrance_Exam_Section_-_Chapter_1',
+ 'display_name': u'Entrance Exam Section - Chapter 1'
+ }
+ ]
+ )
+
+ unlocked_toc = toc_for_course(
+ self.request,
+ self.course,
+ self.entrance_exam.url_name,
+ self.exam_1.url_name,
+ self.field_data_cache
+ )
+
+ for toc_section in expected_unlocked_toc:
+ self.assertIn(toc_section, unlocked_toc)
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index d6ce93563e..0faff94cf3 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -30,7 +30,7 @@ from courseware.tests.factories import StudentModuleFactory, UserFactory, Global
from courseware.tests.tests import LoginEnrollmentTestCase
from xmodule.modulestore.tests.django_utils import (
TEST_DATA_MOCK_MODULESTORE, TEST_DATA_MIXED_TOY_MODULESTORE,
- TEST_DATA_XML_MODULESTORE
+ TEST_DATA_XML_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE
)
from courseware.tests.test_submitting_problems import TestSubmittingProblems
from lms.djangoapps.lms_xblock.runtime import quote_slashes
diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py
index e1d770b804..26fadb0634 100644
--- a/lms/djangoapps/courseware/tests/test_tabs.py
+++ b/lms/djangoapps/courseware/tests/test_tabs.py
@@ -1,6 +1,8 @@
"""
Test cases for tabs.
+Note: Tests covering workflows in the actual tabs.py file begin after line 100
"""
+from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import Http404
from django.test.utils import override_settings
@@ -18,6 +20,11 @@ from xmodule.tabs import CourseTabList
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
+if settings.FEATURES.get('MILESTONES_APP', False):
+ from courseware.tabs import get_course_tab_list
+ from milestones import api as milestones_api
+ from milestones.models import MilestoneRelationshipType
+
@override_settings(MODULESTORE=TEST_DATA_MIXED_TOY_MODULESTORE)
class StaticTabDateTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
@@ -97,3 +104,69 @@ class StaticTabDateTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)
+
+
+@override_settings(MODULESTORE=TEST_DATA_MIXED_CLOSED_MODULESTORE)
+class EntranceExamsTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
+ """
+ Validate tab behavior when dealing with Entrance Exams
+ """
+ if settings.FEATURES.get('ENTRANCE_EXAMS', False):
+
+ def setUp(self):
+ """
+ Test case scaffolding
+ """
+ self.course = CourseFactory.create()
+ self.instructor_tab = ItemFactory.create(
+ category="instructor", parent_location=self.course.location,
+ data="Instructor Tab", display_name="Instructor"
+ )
+ self.extra_tab_2 = ItemFactory.create(
+ category="static_tab", parent_location=self.course.location,
+ data="Extra Tab", display_name="Extra Tab 2"
+ )
+ self.extra_tab_3 = ItemFactory.create(
+ category="static_tab", parent_location=self.course.location,
+ data="Extra Tab", display_name="Extra Tab 3"
+ )
+ self.setup_user()
+ self.enroll(self.course)
+ self.user.is_staff = True
+ self.relationship_types = milestones_api.get_milestone_relationship_types()
+ MilestoneRelationshipType.objects.create(name='requires')
+ MilestoneRelationshipType.objects.create(name='fulfills')
+
+ def test_get_course_tabs_list_entrance_exam_enabled(self):
+ """
+ Unit Test: test_get_course_tabs_list_entrance_exam_enabled
+ """
+ entrance_exam = ItemFactory.create(
+ category="chapter", parent_location=self.course.location,
+ data="Exam Data", display_name="Entrance Exam"
+ )
+ entrance_exam.is_entrance_exam = True
+ milestone = {
+ 'name': 'Test Milestone',
+ 'namespace': '{}.entrance_exams'.format(unicode(self.course.id)),
+ 'description': 'Testing Courseware Tabs'
+ }
+ self.course.entrance_exam_enabled = True
+ self.course.entrance_exam_id = unicode(entrance_exam.location)
+ milestone = milestones_api.add_milestone(milestone)
+ milestones_api.add_course_milestone(
+ unicode(self.course.id),
+ self.relationship_types['REQUIRES'],
+ milestone
+ )
+ milestones_api.add_course_content_milestone(
+ unicode(self.course.id),
+ unicode(entrance_exam.location),
+ self.relationship_types['FULFILLS'],
+ milestone
+ )
+ course_tab_list = get_course_tab_list(self.course, self.user)
+ self.assertEqual(len(course_tab_list), 2)
+ self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
+ self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam')
+ self.assertEqual(course_tab_list[1]['tab_id'], 'instructor')
diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py
index 8c16e8b2d1..e6c871733e 100644
--- a/lms/djangoapps/courseware/views.py
+++ b/lms/djangoapps/courseware/views.py
@@ -68,6 +68,7 @@ import survey.utils
import survey.views
from util.views import ensure_valid_course_key
+
log = logging.getLogger("edx.courseware")
template_imports = {'urllib': urllib}
diff --git a/lms/envs/bok_choy.py b/lms/envs/bok_choy.py
index a3fc1bbce0..14a290b306 100644
--- a/lms/envs/bok_choy.py
+++ b/lms/envs/bok_choy.py
@@ -92,6 +92,10 @@ FEATURES['ENABLE_PREREQUISITE_COURSES'] = True
# Unfortunately, we need to use debug mode to serve staticfiles
DEBUG = True
+########################### Entrance Exams #################################
+FEATURES['MILESTONES_APP'] = True
+FEATURES['ENTRANCE_EXAMS'] = True
+
# Point the URL used to test YouTube availability to our stub YouTube server
YOUTUBE_PORT = 9080
YOUTUBE['API'] = "127.0.0.1:{0}/get_youtube_api/".format(YOUTUBE_PORT)
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 9b884f1bdf..f38651b49d 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -1920,7 +1920,9 @@ OPTIONAL_APPS = (
# edxval
'edxval',
- 'milestones'
+
+ # milestones
+ 'milestones',
)
for app_name in OPTIONAL_APPS:
diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py
index c64ebd76a2..f9d4012ceb 100644
--- a/lms/envs/devstack.py
+++ b/lms/envs/devstack.py
@@ -104,6 +104,15 @@ FEATURES['ADVANCED_SECURITY'] = False
PASSWORD_MIN_LENGTH = None
PASSWORD_COMPLEXITY = {}
+
+########################### Milestones #################################
+FEATURES['MILESTONES_APP'] = True
+
+
+########################### Entrance Exams #################################
+FEATURES['ENTRANCE_EXAMS'] = True
+
+
#####################################################################
# See if the developer has any local overrides.
try:
diff --git a/lms/envs/test.py b/lms/envs/test.py
index 06148c40b7..07964cf30b 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -443,3 +443,9 @@ FEATURES['ENABLE_EDXNOTES'] = True
# Add milestones to Installed apps for testing
INSTALLED_APPS += ('milestones', )
+
+# MILESTONES
+FEATURES['MILESTONES_APP'] = True
+
+# ENTRANCE EXAMS
+FEATURES['ENTRANCE_EXAMS'] = True
diff --git a/lms/templates/courseware/course_navigation.html b/lms/templates/courseware/course_navigation.html
index 635be77502..fe482c5ce6 100644
--- a/lms/templates/courseware/course_navigation.html
+++ b/lms/templates/courseware/course_navigation.html
@@ -12,17 +12,12 @@ def url_class(is_active):
return "active"
return ""
%>
-<%! from xmodule.tabs import CourseTabList %>
-<%! from courseware.access import has_access %>
-<%! from courseware.masquerade import get_course_masquerade %>
+<%! from courseware.tabs import get_course_tab_list %>
<%! from courseware.views import notification_image_for_tab %>
-<%! from django.conf import settings %>
<%! from django.core.urlresolvers import reverse %>
-<%! from django.utils.translation import ugettext as _ %>
<%! from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition %>
<%! from student.models import CourseEnrollment %>
<%
- user_is_enrolled = user.is_authenticated() and CourseEnrollment.is_enrolled(user, course.id)
cohorted_user_partition = get_cohorted_user_partition(course.id)
show_preview_menu = staff_access and active_page in ['courseware', 'info']
is_student_masquerade = masquerade and masquerade.role == 'student'
@@ -59,7 +54,7 @@ def url_class(is_active):
- % for tab in CourseTabList.iterate_displayable(course, settings, user.is_authenticated(), has_access(user, 'staff', course, course.id), user_is_enrolled):
+ % for tab in get_course_tab_list(course, user):
<%
tab_is_active = (tab.tab_id == active_page) or (tab.tab_id == default_tab)
tab_image = notification_image_for_tab(tab, user, course)
diff --git a/pavelib/utils/test/suites/bokchoy_suite.py b/pavelib/utils/test/suites/bokchoy_suite.py
index 29c545f6c5..562cbaf74e 100644
--- a/pavelib/utils/test/suites/bokchoy_suite.py
+++ b/pavelib/utils/test/suites/bokchoy_suite.py
@@ -57,10 +57,11 @@ class BokChoyTestSuite(TestSuite):
print(msg)
bokchoy_utils.check_services()
+ sh("{}/scripts/reset-test-db.sh".format(Env.REPO_ROOT))
+
if not self.fasttest:
# Process assets and set up database for bok-choy tests
# Reset the database
- sh("{}/scripts/reset-test-db.sh".format(Env.REPO_ROOT))
# Collect static assets
sh("paver update_assets --settings=bok_choy")