diff --git a/common/djangoapps/course_modes/admin.py b/common/djangoapps/course_modes/admin.py index 58c458236a..ad6ec016ce 100644 --- a/common/djangoapps/course_modes/admin.py +++ b/common/djangoapps/course_modes/admin.py @@ -1,4 +1,36 @@ from ratelimitbackend import admin from course_modes.models import CourseMode +from django import forms -admin.site.register(CourseMode) +from opaque_keys import InvalidKeyError +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.keys import CourseKey +from xmodule.modulestore.locations import SlashSeparatedCourseKey + + +class CourseModeForm(forms.ModelForm): + + class Meta: + model = CourseMode + + def clean_course_id(self): + course_id = self.cleaned_data['course_id'] + try: + course_key = CourseKey.from_string(course_id) + except InvalidKeyError: + try: + course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) + except InvalidKeyError: + raise forms.ValidationError("Cannot make a valid CourseKey from id {}!".format(course_id)) + + if not modulestore().has_course(course_key): + raise forms.ValidationError("Cannot find course with id {} in the modulestore".format(course_id)) + + return course_key + + +class CourseModeAdmin(admin.ModelAdmin): + form = CourseModeForm + + +admin.site.register(CourseMode, CourseModeAdmin) diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index 2657f877f6..abba0e1556 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -126,5 +126,5 @@ class CourseMode(models.Model): def __unicode__(self): return u"{} : {}, min={}, prices={}".format( - self.course_id, self.mode_slug, self.min_price, self.suggested_prices + self.course_id.to_deprecated_string(), self.mode_slug, self.min_price, self.suggested_prices ) diff --git a/common/djangoapps/embargo/forms.py b/common/djangoapps/embargo/forms.py index ce7a6a00da..0d7df8d40a 100644 --- a/common/djangoapps/embargo/forms.py +++ b/common/djangoapps/embargo/forms.py @@ -11,6 +11,7 @@ import socket from xmodule.modulestore.django import modulestore from opaque_keys import InvalidKeyError +from xmodule.modulestore.keys import CourseKey from xmodule.modulestore.locations import SlashSeparatedCourseKey @@ -24,31 +25,24 @@ class EmbargoedCourseForm(forms.ModelForm): # pylint: disable=incomplete-protoc """Validate the course id""" cleaned_id = self.cleaned_data["course_id"] - try: - course_id = SlashSeparatedCourseKey.from_deprecated_string(cleaned_id) - + course_key = CourseKey.from_string(cleaned_id) except InvalidKeyError: + try: + course_key = SlashSeparatedCourseKey.from_deprecated_string(cleaned_id) + except InvalidKeyError: + msg = 'COURSE NOT FOUND' + msg += u' --- Entered course id was: "{0}". '.format(cleaned_id) + msg += 'Please recheck that you have supplied a valid course id.' + raise forms.ValidationError(msg) + + if not modulestore().has_course(course_key): msg = 'COURSE NOT FOUND' - msg += u' --- Entered course id was: "{0}". '.format(cleaned_id) + msg += u' --- Entered course id was: "{0}". '.format(course_key.to_deprecated_string()) msg += 'Please recheck that you have supplied a valid course id.' raise forms.ValidationError(msg) - # Try to get the course. If this returns None, it's not a real course - try: - course = modulestore().get_course(course_id) - except ValueError: - msg = 'COURSE NOT FOUND' - msg += u' --- Entered course id was: "{0}". '.format(course_id.to_deprecated_string()) - msg += 'Please recheck that you have supplied a valid course id.' - raise forms.ValidationError(msg) - if not course: - msg = 'COURSE NOT FOUND' - msg += u' --- Entered course id was: "{0}". '.format(course_id.to_deprecated_string()) - msg += 'Please recheck that you have supplied a valid course id.' - raise forms.ValidationError(msg) - - return course_id + return course_key class EmbargoedStateForm(forms.ModelForm): # pylint: disable=incomplete-protocol diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py index 274c97dd70..cbffc85d89 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py @@ -608,10 +608,14 @@ class MongoModuleStore(ModuleStoreWriteBase): otherwise, do a case sensitive search """ assert(isinstance(course_key, SlashSeparatedCourseKey)) - course_query = self._course_key_to_son(course_key) + location = course_key.make_usage_key('course', course_key.run) if ignore_case: + course_query = location.to_deprecated_son('_id.') for key in course_query.iterkeys(): - course_query[key] = re.compile(r"(?i)^{}$".format(course_query[key])) + if isinstance(course_query[key], basestring): + course_query[key] = re.compile(r"(?i)^{}$".format(course_query[key])) + else: + course_query = {'_id': location.to_deprecated_son()} return self.collection.find_one(course_query, fields={'_id': True}) is not None def has_item(self, usage_key): diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index 3079c891ac..d86221a7b6 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -15,6 +15,7 @@ from xmodule.errortracker import make_error_tracker from .store_utilities import rewrite_nonportable_content_links import xblock from xmodule.tabs import CourseTabList +from xmodule.modulestore.exceptions import InvalidLocationError log = logging.getLogger(__name__) @@ -165,6 +166,7 @@ def import_from_xml( dest_course_id = course_key if create_new_course: + # this tests if exactly this course (ignoring case) exists; so, it checks the run if store.has_course(dest_course_id, ignore_case=True): log.debug( "Skipping import of course with id, {0}," @@ -172,7 +174,15 @@ def import_from_xml( ) continue else: - store.create_course(dest_course_id.org, dest_course_id.offering) + try: + store.create_course(dest_course_id.org, dest_course_id.offering) + except InvalidLocationError: + # course w/ same org and course exists and store is old mongo + log.debug( + "Skipping import of course with id, {0}," + "since it collides with an existing one".format(dest_course_id) + ) + continue try: # turn off all write signalling while importing as this diff --git a/lms/djangoapps/bulk_email/forms.py b/lms/djangoapps/bulk_email/forms.py index 92c47cdcb0..326a114ba1 100644 --- a/lms/djangoapps/bulk_email/forms.py +++ b/lms/djangoapps/bulk_email/forms.py @@ -11,6 +11,8 @@ from bulk_email.models import CourseEmailTemplate, COURSE_EMAIL_MESSAGE_BODY_TAG from opaque_keys import InvalidKeyError from xmodule.modulestore import XML_MODULESTORE_TYPE from xmodule.modulestore.django import modulestore +from opaque_keys import InvalidKeyError +from xmodule.modulestore.keys import CourseKey from xmodule.modulestore.locations import SlashSeparatedCourseKey log = logging.getLogger(__name__) @@ -60,24 +62,27 @@ class CourseAuthorizationAdminForm(forms.ModelForm): # pylint: disable=R0924 """Validate the course id""" cleaned_id = self.cleaned_data["course_id"] try: - course_id = SlashSeparatedCourseKey.from_deprecated_string(cleaned_id) + course_key = CourseKey.from_string(cleaned_id) except InvalidKeyError: - msg = u'Course id invalid.' - msg += u' --- Entered course id was: "{0}". '.format(cleaned_id) - msg += 'Please recheck that you have supplied a valid course id.' - raise forms.ValidationError(msg) + try: + course_key = SlashSeparatedCourseKey.from_deprecated_string(cleaned_id) + except InvalidKeyError: + msg = u'Course id invalid.' + msg += u' --- Entered course id was: "{0}". '.format(cleaned_id) + msg += 'Please recheck that you have supplied a valid course id.' + raise forms.ValidationError(msg) - if not modulestore().has_course(course_id): + if not modulestore().has_course(course_key): msg = u'COURSE NOT FOUND' - msg += u' --- Entered course id was: "{0}". '.format(course_id.to_deprecated_string()) + msg += u' --- Entered course id was: "{0}". '.format(course_key.to_deprecated_string()) msg += 'Please recheck that you have supplied a valid course id.' raise forms.ValidationError(msg) # Now, try and discern if it is a Studio course - HTML editor doesn't work with XML courses - is_studio_course = modulestore().get_modulestore_type(course_id) != XML_MODULESTORE_TYPE + is_studio_course = modulestore().get_modulestore_type(course_key) != XML_MODULESTORE_TYPE if not is_studio_course: msg = "Course Email feature is only available for courses authored in Studio. " - msg += '"{0}" appears to be an XML backed course.'.format(course_id.to_deprecated_string()) + msg += '"{0}" appears to be an XML backed course.'.format(course_key.to_deprecated_string()) raise forms.ValidationError(msg) - return course_id.to_deprecated_string() + return course_key