def _create_new_course(request, course_key, fields): """ Create a new course. Returns the URL for the course overview page. """ # Set a unique wiki_slug for newly created courses. To maintain active wiki_slugs for # existing xml courses this cannot be changed in CourseDescriptor. # # TODO get rid of defining wiki slug in this org/course/run specific way and reconcile # w/ xmodule.course_module.CourseDescriptor.__init__ wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) # Creating the course raises InvalidLocationError if an existing course with this org/name is found new_course = modulestore().create_course( course_key.org, course_key.course, course_key.run, request.user.id, fields=fields, ) # Make sure user has instructor and staff access to the new course add_instructor(new_course.id, request.user, request.user) # Initialize permissions for user in the new course initialize_permissions(new_course.id, request.user) return JsonResponse({ 'url': reverse_course_url('course_handler', new_course.id) })
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ # import here, at top level this import prevents the celery workers from starting up correctly from edxval.api import copy_course_videos try: # deserialize the payload source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string( destination_course_key_string) fields = deserialize_fields(fields) if fields else None # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) return "succeeded" except DuplicateCourseError as exc: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key) logging.exception(u'Course Rerun Error') return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key) logging.exception(u'Course Rerun Error') try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return "exception: " + unicode(exc)
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ try: # deserialize the keys source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string( destination_course_key_string) # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) return "succeeded" except DuplicateCourseError as exc: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc) return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc) try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return "exception: " + unicode(exc)
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ # import here, at top level this import prevents the celery workers from starting up correctly from edxval.api import copy_course_videos try: # deserialize the payload source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string(destination_course_key_string) fields = deserialize_fields(fields) if fields else None # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) return "succeeded" except DuplicateCourseError as exc: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key) logging.exception(u'Course Rerun Error') return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key) logging.exception(u'Course Rerun Error') try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return "exception: " + unicode(exc)
def get_master_course(user=None, command=None): from contentstore.utils import add_instructor, initialize_permissions from courseware.courses import get_course_by_id from opaque_keys.edx.locations import SlashSeparatedCourseKey from student.roles import CourseRole from xmodule.modulestore.exceptions import InvalidLocationError if not user: user = User.objects.get(id=ADMIN_USER_ID) display_name = "LabsterX Master" org, number, run = COURSE_ID.split('/') try: course_key = SlashSeparatedCourseKey(org, number, run) fields = {'display_name': display_name} wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = get_modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) command and command.stdout.write("name: {}\n".format(course.display_name)) except InvalidLocationError: course = get_course_by_id(course_key) return course
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ try: # deserialize the keys source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string(destination_course_key_string) # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) return "succeeded" except DuplicateCourseError as exc: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc) return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc) try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return "exception: " + unicode(exc)
def rerun_course(source_course_key, destination_course_key, user_id, fields=None): """ Reruns a course in a new celery task. """ try: modulestore().clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key, exception=exc) # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id)
def get_or_create_course(source, target, user): source_course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(source)) display_name = source_course.display_name org, number, run = target.split('/') course_key = SlashSeparatedCourseKey(org, number, run) fields = {'display_name': display_name} wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) try: if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) except InvalidLocationError: course = get_course(course_key) else: # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) return course
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ # import here, at top level this import prevents the celery workers from starting up correctly from edxval.api import copy_course_videos source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string( destination_course_key_string) try: # deserialize the payload fields = deserialize_fields(fields) if fields else None # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) # Copy OrganizationCourse organization_course = OrganizationCourse.objects.filter( course_id=source_course_key_string).first() if organization_course: clone_instance(organization_course, {'course_id': destination_course_key_string}) # Copy RestrictedCourse restricted_course = RestrictedCourse.objects.filter( course_key=source_course_key).first() if restricted_course: country_access_rules = CountryAccessRule.objects.filter( restricted_course=restricted_course) new_restricted_course = clone_instance( restricted_course, {'course_key': destination_course_key}) for country_access_rule in country_access_rules: clone_instance(country_access_rule, {'restricted_course': new_restricted_course}) return "succeeded" except DuplicateCourseError: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key) LOGGER.exception(u'Course Rerun Error') return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key) LOGGER.exception(u'Course Rerun Error') try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return u"exception: " + text_type(exc)
def rerun_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ # import here, at top level this import prevents the celery workers from starting up correctly from edxval.api import copy_course_videos source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string(destination_course_key_string) try: # deserialize the payload fields = deserialize_fields(fields) if fields else None # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) # Copy OrganizationCourse organization_course = OrganizationCourse.objects.filter(course_id=source_course_key_string).first() if organization_course: clone_instance(organization_course, {'course_id': destination_course_key_string}) # Copy RestrictedCourse restricted_course = RestrictedCourse.objects.filter(course_key=source_course_key).first() if restricted_course: country_access_rules = CountryAccessRule.objects.filter(restricted_course=restricted_course) new_restricted_course = clone_instance(restricted_course, {'course_key': destination_course_key}) for country_access_rule in country_access_rules: clone_instance(country_access_rule, {'restricted_course': new_restricted_course}) return "succeeded" except DuplicateCourseError: # do NOT delete the original course, only update the status CourseRerunState.objects.failed(course_key=destination_course_key) LOGGER.exception(u'Course Rerun Error') return "duplicate course" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed CourseRerunState.objects.failed(course_key=destination_course_key) LOGGER.exception(u'Course Rerun Error') try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return u"exception: " + text_type(exc)
def force_create_course(source, target, user, extra_fields=None): source_course_key = SlashSeparatedCourseKey.from_deprecated_string(source) source_course = get_course_by_id(source_course_key) display_name = source_course.display_name fields = {'display_name': display_name} # duplicated_fields = [ # 'key_dates', 'video', # 'course_staff_short', 'course_staff_extended', # 'requirements', 'textbook', 'faq', 'more_info', # 'number', 'instructors', 'end_date', # 'prerequisites', 'ocw_links', # ] # for field in duplicated_fields: # fields[field] = getattr(source_course, field) course = None start_index = 0 org, original_number, run = target.split('/') number = original_number while course is None: course_key = SlashSeparatedCourseKey(org, number, run) wiki_slug = u"{0}.{1}.{2}".format(course_key.org, course_key.course, course_key.run) definition_data = {'wiki_slug': wiki_slug} fields.update(definition_data) if extra_fields: fields.update(extra_fields) try: if CourseRole.course_group_already_exists(course_key): raise InvalidLocationError() course = modulestore().create_course( course_key.org, course_key.course, course_key.run, user.id, fields=fields, ) except InvalidLocationError: start_index += 1 number = "{}{}".format(original_number, start_index) continue else: # Make sure user has instructor and staff access to the new course add_instructor(course.id, user, user) # Initialize permissions for user in the new course initialize_permissions(course.id, user) copy_about_fields(user, source_course_key, course_key, course) UserProfile.objects\ .filter(user_id=user.id)\ .exclude(user_type=UserProfile.USER_TYPE_TEACHER)\ .update(user_type=UserProfile.USER_TYPE_TEACHER) return course
def clone_course(source_course_key_string, destination_course_key_string, user_id, fields=None): """ Reruns a course in a new celery task. """ # import here, at top level this import prevents the celery workers from starting up correctly from edxval.api import copy_course_videos from contentstore.utils import initialize_permissions from contentstore.courseware_index import SearchIndexingError from contentstore.views.course import reindex_course_and_check_access # deserialize the payload source_course_key = CourseKey.from_string(source_course_key_string) destination_course_key = CourseKey.from_string( destination_course_key_string) try: # use the split modulestore as the store for the rerun course, # as the Mongo modulestore doesn't support multiple runs of the same course. store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) # set initial permissions for the user to access the course. user = User.objects.get(id=user_id) initialize_permissions(destination_course_key, user) # add course intructor and staff roles to the new user CourseInstructorRole(destination_course_key).add_users(user) CourseStaffRole(destination_course_key).add_users(user) # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) return "succeeded" except DuplicateCourseError as exc: # do NOT delete the original course, only update the status logging.exception(u'Course Clone Error') return "duplicate course" except SearchIndexingError as search_err: logging.exception(u'Course Clone index Error') return "index error" # catch all exceptions so we can update the state and properly cleanup the course. except Exception as exc: # pylint: disable=broad-except # update state: Failed logging.exception(u'Course Clone Error') try: # cleanup any remnants of the course modulestore().delete_course(destination_course_key, user_id) except ItemNotFoundError: # it's possible there was an error even before the course module was created pass return "exception: " + unicode(exc)