コード例 #1
0
ファイル: assets.py プロジェクト: yellowsignz/edx-platform
def _get_asset_json(display_name, content_type, date, location,
                    thumbnail_location, locked):
    '''
    Helper method for formatting the asset information to send to client.
    '''
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name':
        display_name,
        'content_type':
        content_type,
        'date_added':
        get_default_time_display(date),
        'url':
        asset_url,
        'external_url':
        external_url,
        'portable_url':
        StaticContent.get_static_path_from_location(location),
        'thumbnail':
        StaticContent.serialize_asset_key_with_slash(thumbnail_location)
        if thumbnail_location else None,
        'locked':
        locked,
        # needed for Backbone delete/update.
        'id':
        unicode(location)
    }
コード例 #2
0
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.get_url_path_from_location(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name':
        display_name,
        'date_added':
        strftime_localized(date, "%Y年%m月%d日 %H:%M"),
        'url':
        asset_url,
        'external_url':
        external_url,
        'portable_url':
        StaticContent.get_static_path_from_location(location),
        'thumbnail':
        StaticContent.get_url_path_from_location(thumbnail_location)
        if thumbnail_location is not None else None,
        'locked':
        locked,
        # Needed for Backbone delete/update.
        'id':
        asset_url
    }
コード例 #3
0
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = location.to_deprecated_string()
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name':
        display_name,
        'date_added':
        get_default_time_display(date),
        'url':
        asset_url,
        'external_url':
        external_url,
        'portable_url':
        StaticContent.get_static_path_from_location(location),
        'thumbnail':
        thumbnail_location.to_deprecated_string()
        if thumbnail_location is not None else None,
        'locked':
        locked,
        # Needed for Backbone delete/update.
        'id':
        unicode(location)
    }
コード例 #4
0
ファイル: assets.py プロジェクト: colaraz/edx-platform
def _get_asset_json(display_name, content_type, date, location,
                    thumbnail_location, locked):
    '''
    Helper method for formatting the asset information to send to client.
    '''

    # Colaraz Custom: overriding this to get site base web link of the asset(s)
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    external_url = 'https://' + configuration_helpers.get_value(
        'LMS_BASE') + asset_url

    return {
        'display_name':
        display_name,
        'content_type':
        content_type,
        'date_added':
        get_default_time_display(date),
        'url':
        asset_url,
        'external_url':
        external_url,
        'portable_url':
        StaticContent.get_static_path_from_location(location),
        'thumbnail':
        StaticContent.serialize_asset_key_with_slash(thumbnail_location)
        if thumbnail_location else None,
        'locked':
        locked,
        # needed for Backbone delete/update.
        'id':
        unicode(location)
    }
コード例 #5
0
ファイル: assets.py プロジェクト: vedraiyani/edunext-platform
def _get_asset_json(display_name, content_type, date, location,
                    thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    # eduNEXT 14.07.2016
    lms_base = microsite.get_value_for_org(location.org, 'SITE_NAME',
                                           settings.LMS_BASE)
    external_url = lms_base + asset_url
    return {
        'display_name':
        display_name,
        'content_type':
        content_type,
        'date_added':
        get_default_time_display(date),
        'url':
        asset_url,
        'external_url':
        external_url,
        'portable_url':
        StaticContent.get_static_path_from_location(location),
        'thumbnail':
        StaticContent.serialize_asset_key_with_slash(thumbnail_location)
        if thumbnail_location else None,
        'locked':
        locked,
        # Needed for Backbone delete/update.
        'id':
        unicode(location)
    }
コード例 #6
0
def _get_asset_json_for_editorjs(display_name, content_type, date, location,
                                 thumbnail_location, locked):
    '''
    Helper method for formatting the asset information to send to client.
    '''
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        "success": 1,
        "file": {
            'url':
            asset_url,
            'display_name':
            display_name,
            'content_type':
            content_type,
            'date_added':
            get_default_time_display(date),
            'asset_url':
            asset_url,
            'external_url':
            external_url,
            'portable_url':
            StaticContent.get_static_path_from_location(location),
            'thumbnail':
            StaticContent.serialize_asset_key_with_slash(thumbnail_location)
            if thumbnail_location else None,
            'locked':
            locked,
            'id':
            six.text_type(location)
        }
    }
コード例 #7
0
ファイル: assets.py プロジェクト: praveen-pal/edx-platform
def asset_index(request, org, course, name):
    """
    Display an editable asset library

    org, course, name: Attributes of the Location for the item to edit
    """
    location = get_location_and_verify_access(request, org, course, name)

    upload_asset_callback_url = reverse('upload_asset', kwargs={
        'org': org,
        'course': course,
        'coursename': name
    })

    course_module = modulestore().get_item(location)

    course_reference = StaticContent.compute_location(org, course, name)
    assets = contentstore().get_all_content_for_course(course_reference)

    # sort in reverse upload date order
    assets = sorted(assets, key=lambda asset: asset['uploadDate'], reverse=True)

    if request.META.get('HTTP_ACCEPT', "").startswith("application/json"):
        return JsonResponse(assets_to_json_dict(assets))

    asset_display = []
    for asset in assets:
        asset_id = asset['_id']
        display_info = {}
        display_info['displayname'] = asset['displayname']
        display_info['uploadDate'] = get_default_time_display(asset['uploadDate'])

        asset_location = StaticContent.compute_location(asset_id['org'], asset_id['course'], asset_id['name'])
        display_info['url'] = StaticContent.get_url_path_from_location(asset_location)
        display_info['portable_url'] = StaticContent.get_static_path_from_location(asset_location)

        # note, due to the schema change we may not have a 'thumbnail_location' in the result set
        _thumbnail_location = asset.get('thumbnail_location', None)
        thumbnail_location = Location(_thumbnail_location) if _thumbnail_location is not None else None
        display_info['thumb_url'] = StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None

        asset_display.append(display_info)

    return render_to_response('asset_index.html', {
        'context_course': course_module,
        'assets': asset_display,
        'upload_asset_callback_url': upload_asset_callback_url,
        'remove_asset_callback_url': reverse('remove_asset', kwargs={
            'org': org,
            'course': course,
            'name': name
        })
    })
コード例 #8
0
ファイル: assets.py プロジェクト: AzizYosofi/edx-platform
def asset_index(request, org, course, name):
    """
    Display an editable asset library

    org, course, name: Attributes of the Location for the item to edit
    """
    location = get_location_and_verify_access(request, org, course, name)

    upload_asset_callback_url = reverse('upload_asset', kwargs={
        'org': org,
        'course': course,
        'coursename': name
    })

    course_module = modulestore().get_item(location)

    course_reference = StaticContent.compute_location(org, course, name)
    assets = contentstore().get_all_content_for_course(course_reference)

    # sort in reverse upload date order
    assets = sorted(assets, key=lambda asset: asset['uploadDate'], reverse=True)

    if request.META.get('HTTP_ACCEPT', "").startswith("application/json"):
        return JsonResponse(assets_to_json_dict(assets))

    asset_display = []
    for asset in assets:
        asset_id = asset['_id']
        display_info = {}
        display_info['displayname'] = asset['displayname']
        display_info['uploadDate'] = get_default_time_display(asset['uploadDate'])

        asset_location = StaticContent.compute_location(asset_id['org'], asset_id['course'], asset_id['name'])
        display_info['url'] = StaticContent.get_url_path_from_location(asset_location)
        display_info['portable_url'] = StaticContent.get_static_path_from_location(asset_location)

        # note, due to the schema change we may not have a 'thumbnail_location' in the result set
        _thumbnail_location = asset.get('thumbnail_location', None)
        thumbnail_location = Location(_thumbnail_location) if _thumbnail_location is not None else None
        display_info['thumb_url'] = StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None

        asset_display.append(display_info)

    return render_to_response('asset_index.html', {
        'context_course': course_module,
        'assets': asset_display,
        'upload_asset_callback_url': upload_asset_callback_url,
        'remove_asset_callback_url': reverse('remove_asset', kwargs={
            'org': org,
            'course': course,
            'name': name
        })
    })
コード例 #9
0
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.get_url_path_from_location(location)
    return {
        'display_name': display_name,
        'date_added': get_default_time_display(date),
        'url': asset_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None,
        'locked': locked,
        # Needed for Backbone delete/update.
        'id': asset_url
    }
コード例 #10
0
ファイル: assets.py プロジェクト: chenkaigithub/edx-platform
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.get_url_path_from_location(location)
    return {
        'display_name': display_name,
        'date_added': get_default_time_display(date),
        'url': asset_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None,
        'locked': locked,
        # Needed for Backbone delete/update.
        'id': asset_url
    }
コード例 #11
0
ファイル: assets.py プロジェクト: altsen/xiaodun-platform
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.get_url_path_from_location(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name': display_name,
        'date_added': strftime_localized(date, "%m %d, %Y %H:%M"),
        'url': asset_url,
        'external_url': external_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None,
        'locked': locked,
        # Needed for Backbone delete/update.
        'id': asset_url
    }
コード例 #12
0
ファイル: assets.py プロジェクト: AdityaKashyap/edx-platform
def _get_asset_json(display_name, date, location, thumbnail_location, locked):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = _add_slash(location.to_deprecated_string())
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name': display_name,
        'date_added': get_default_time_display(date),
        'url': asset_url,
        'external_url': external_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': _add_slash(unicode(thumbnail_location)) if thumbnail_location else None,
        'locked': locked,
        # Needed for Backbone delete/update.
        'id': unicode(location)
    }
コード例 #13
0
ファイル: views.py プロジェクト: nttlong/lv-open-edx
def _get_asset_json(display_name, content_type, date, location, thumbnail_location, locked,name_creater):
    """
    Helper method for formatting the asset information to send to client.
    """
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    external_url = 'localhost:8000' + asset_url
    return {
        'display_name': display_name,
        'content_type': content_type,
        'date_added': get_default_time_display(date),
        'url': asset_url,
        'external_url': external_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.serialize_asset_key_with_slash(thumbnail_location) if thumbnail_location else None,
        'locked': locked,
        'name_creater':name_creater
    }
コード例 #14
0
ファイル: assets.py プロジェクト: AlexxNica/edx-platform
def _get_asset_json(display_name, content_type, date, location, thumbnail_location, locked):
    '''
    Helper method for formatting the asset information to send to client.
    '''
    asset_url = StaticContent.serialize_asset_key_with_slash(location)
    external_url = settings.LMS_BASE + asset_url
    return {
        'display_name': display_name,
        'content_type': content_type,
        'date_added': get_default_time_display(date),
        'url': asset_url,
        'external_url': external_url,
        'portable_url': StaticContent.get_static_path_from_location(location),
        'thumbnail': StaticContent.serialize_asset_key_with_slash(thumbnail_location) if thumbnail_location else None,
        'locked': locked,
        # needed for Backbone delete/update.
        'id': unicode(location)
    }
コード例 #15
0
ファイル: xml_importer.py プロジェクト: msaqib52/edx-platform
    def static_updater(self, course, source_courselike, courselike_key, dest_id, runtime):
        """
        Update special static assets, such as PDF textbooks and wiki resources.
        """
        for entry in course.pdf_textbooks:
            for chapter in entry.get('chapters', []):
                if StaticContent.is_c4x_path(chapter.get('url', '')):
                    asset_key = StaticContent.get_location_from_path(chapter['url'])
                    chapter['url'] = StaticContent.get_static_path_from_location(asset_key)

        # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
        # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
        # values then remap it so that the wiki does not point to the old wiki.
        if courselike_key != course.id:
            if self.xml_module_store.course_run is None:
                original_course_run = courselike_key.run
            else:
                original_course_run = self.xml_module_store.course_run

            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                courselike_key.org,
                courselike_key.course,
                original_course_run,
            )
            if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == courselike_key.course:
                course.wiki_slug = u'{0}.{1}.{2}'.format(
                    course.id.org,
                    course.id.course,
                    course.id.run,
                )

        # cdodge: more hacks (what else). Seems like we have a
        # problem when importing a course (like 6.002) which
        # does not have any tabs defined in the policy file.
        # The import goes fine and then displays fine in LMS,
        # but if someone tries to add a new tab in the CMS, then
        # the LMS barfs because it expects that -- if there are
        # *any* tabs -- then there at least needs to be
        # some predefined ones
        if course.tabs is None or len(course.tabs) == 0:
            CourseTabList.initialize_default(course)
コード例 #16
0
    def static_updater(self, course, source_courselike, courselike_key,
                       dest_id, runtime):
        """
        Update special static assets, such as PDF textbooks and wiki resources.
        """
        for entry in course.pdf_textbooks:
            for chapter in entry.get('chapters', []):
                if StaticContent.is_c4x_path(chapter.get('url', '')):
                    asset_key = StaticContent.get_location_from_path(
                        chapter['url'])
                    chapter[
                        'url'] = StaticContent.get_static_path_from_location(
                            asset_key)

        # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
        # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
        # values then remap it so that the wiki does not point to the old wiki.
        if courselike_key != course.id:
            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                courselike_key.org, courselike_key.course, courselike_key.run)
            if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == courselike_key.course:
                course.wiki_slug = u'{0}.{1}.{2}'.format(
                    course.id.org,
                    course.id.course,
                    course.id.run,
                )

        # cdodge: more hacks (what else). Seems like we have a
        # problem when importing a course (like 6.002) which
        # does not have any tabs defined in the policy file.
        # The import goes fine and then displays fine in LMS,
        # but if someone tries to add a new tab in the CMS, then
        # the LMS barfs because it expects that -- if there are
        # *any* tabs -- then there at least needs to be
        # some predefined ones
        if course.tabs is None or len(course.tabs) == 0:
            CourseTabList.initialize_default(course)
コード例 #17
0
ファイル: test_assets.py プロジェクト: nosenat/edx-platform
 def test_static_url_generation(self):
     location = Location(["i4x", "foo", "bar", "asset", "my_file_name.jpg"])
     path = StaticContent.get_static_path_from_location(location)
     self.assertEquals(path, "/static/my_file_name.jpg")
コード例 #18
0
def remap_namespace(module, target_location_namespace):
    if target_location_namespace is None:
        return module

    original_location = module.location

    # This looks a bit wonky as we need to also change the 'name' of the
    # imported course to be what the caller passed in
    if module.location.category != 'course':
        _update_module_location(
            module,
            module.location.replace(
                tag=target_location_namespace.tag,
                org=target_location_namespace.org,
                course=target_location_namespace.course
            )
        )

    else:
        #
        # module is a course module
        #
        module.location = module.location.replace(
            tag=target_location_namespace.tag,
            org=target_location_namespace.org,
            course=target_location_namespace.course,
            name=target_location_namespace.name
        )
        # There is more re-namespacing work we have to do when
        # importing course modules

        # remap pdf_textbook urls to portable static URLs
        for entry in module.pdf_textbooks:
            for chapter in entry.get('chapters', []):
                if StaticContent.is_c4x_path(chapter.get('url', '')):
                    chapter_loc = StaticContent.get_location_from_path(chapter['url'])
                    chapter['url'] = StaticContent.get_static_path_from_location(
                        chapter_loc
                    )

        # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
        # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
        # values then remap it so that the wiki does not point to the old wiki.
        if original_location.course_id != target_location_namespace.course_id:
            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                original_location.org,
                original_location.course,
                original_location.name
            )
            if module.wiki_slug == original_unique_wiki_slug or module.wiki_slug == original_location.course:
                module.wiki_slug = u'{0}.{1}.{2}'.format(
                    target_location_namespace.org,
                    target_location_namespace.course,
                    target_location_namespace.name,
                )

        module.save()

    all_fields = module.get_explicitly_set_fields_by_scope(Scope.content)
    all_fields.update(module.get_explicitly_set_fields_by_scope(Scope.settings))
    if hasattr(module, 'children'):
        all_fields['children'] = module.children

    def convert_ref(reference):
        """
        Convert a reference to the new namespace, but only
        if the original namespace matched the original course.

        Otherwise, returns the input value.
        """
        new_ref = reference
        ref = Location(reference)
        in_original_namespace = (original_location.tag == ref.tag and
                                 original_location.org == ref.org and
                                 original_location.course == ref.course)
        if in_original_namespace:
            new_ref = ref.replace(
                tag=target_location_namespace.tag,
                org=target_location_namespace.org,
                course=target_location_namespace.course
            ).url()
        return new_ref

    for field_name in all_fields:
        field_object = module.fields.get(field_name)
        if isinstance(field_object, Reference):
            new_ref = convert_ref(getattr(module, field_name))
            setattr(module, field_name, new_ref)
            module.save()
        elif isinstance(field_object, ReferenceList):
            references = getattr(module, field_name)
            new_references = [convert_ref(reference) for reference in references]
            setattr(module, field_name, new_references)
            module.save()
        elif isinstance(field_object, ReferenceValueDict):
            reference_dict = getattr(module, field_name)
            new_reference_dict = {
                key: convert_ref(reference)
                for key, reference
                in reference_dict.items()
            }
            setattr(module, field_name, new_reference_dict)
            module.save()

    return module
コード例 #19
0
def import_from_xml(store,
                    data_dir,
                    course_dirs=None,
                    default_class='xmodule.raw_module.RawDescriptor',
                    load_error_modules=True,
                    static_content_store=None,
                    target_course_id=None,
                    verbose=False,
                    draft_store=None,
                    do_import_static=True,
                    create_new_course=False):
    """
    Import the specified xml data_dir into the "store" modulestore,
    using org and course as the location org and course.

    course_dirs: If specified, the list of course_dirs to load. Otherwise, load
    all course dirs

    target_course_id is the CourseKey that all modules should be remapped to
    after import off disk. We do this remapping as a post-processing step
    because there's logic in the importing which expects a 'url_name' as an
    identifier to where things are on disk
    e.g. ../policies/<url_name>/policy.json as well as metadata keys in
    the policy.json. so we need to keep the original url_name during import

    :param do_import_static:
        if False, then static files are not imported into the static content
        store. This can be employed for courses which have substantial
        unchanging static content, which is to inefficient to import every
        time the course is loaded. Static content for some courses may also be
        served directly by nginx, instead of going through django.

    : create_new_course:
        If True, then courses whose ids already exist in the store are not imported.
        The check for existing courses is case-insensitive.
    """

    xml_module_store = XMLModuleStore(
        data_dir,
        default_class=default_class,
        course_dirs=course_dirs,
        load_error_modules=load_error_modules,
        xblock_mixins=store.xblock_mixins,
        xblock_select=store.xblock_select,
    )

    # If we're going to remap the course_id, then we can only do that with
    # a single course

    if target_course_id:
        assert (len(xml_module_store.modules) == 1)

    # NOTE: the XmlModuleStore does not implement get_items()
    # which would be a preferable means to enumerate the entire collection
    # of course modules. It will be left as a TBD to implement that
    # method on XmlModuleStore.
    course_items = []
    for course_key in xml_module_store.modules.keys():

        if target_course_id is not None:
            dest_course_id = target_course_id
        else:
            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},"
                          "since it collides with an existing one".format(
                              dest_course_id))
                continue
            else:
                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
            # is a high volume operation on stores that need it
            if hasattr(store, 'ignore_write_events_on_courses'):
                store.ignore_write_events_on_courses.add(dest_course_id)

            course_data_path = None

            if verbose:
                log.debug(
                    "Scanning {0} for course module...".format(course_key))

            # Quick scan to get course module as we need some info from there.
            # Also we need to make sure that the course module is committed
            # first into the store
            for module in xml_module_store.modules[course_key].itervalues():
                if module.scope_ids.block_type == 'course':
                    course_data_path = path(data_dir) / module.data_dir

                    log.debug(u'======> IMPORTING course {course_key}'.format(
                        course_key=course_key, ))

                    if not do_import_static:
                        # for old-style xblock where this was actually linked to kvs
                        module.static_asset_path = module.data_dir
                        module.save()
                        log.debug('course static_asset_path={path}'.format(
                            path=module.static_asset_path))

                    log.debug('course data_dir={0}'.format(module.data_dir))

                    course = import_module(module,
                                           store,
                                           course_key,
                                           dest_course_id,
                                           do_import_static=do_import_static)

                    for entry in course.pdf_textbooks:
                        for chapter in entry.get('chapters', []):
                            if StaticContent.is_c4x_path(chapter.get(
                                    'url', '')):
                                asset_key = StaticContent.get_location_from_path(
                                    chapter['url'])
                                chapter[
                                    'url'] = StaticContent.get_static_path_from_location(
                                        asset_key)

                    # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
                    # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
                    # values then remap it so that the wiki does not point to the old wiki.
                    if course_key != course.id:
                        original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                            course_key.org, course_key.course, course_key.run)
                        if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == course_key.course:
                            course.wiki_slug = u'{0}.{1}.{2}'.format(
                                course.id.org,
                                course.id.course,
                                course.id.run,
                            )

                    # cdodge: more hacks (what else). Seems like we have a
                    # problem when importing a course (like 6.002) which
                    # does not have any tabs defined in the policy file.
                    # The import goes fine and then displays fine in LMS,
                    # but if someone tries to add a new tab in the CMS, then
                    # the LMS barfs because it expects that -- if there are
                    # *any* tabs -- then there at least needs to be
                    # some predefined ones
                    if course.tabs is None or len(course.tabs) == 0:
                        CourseTabList.initialize_default(course)

                    store.update_item(course)

                    course_items.append(course)

            # then import all the static content
            if static_content_store is not None and do_import_static:
                # first pass to find everything in /static/
                import_static_content(course_data_path,
                                      static_content_store,
                                      dest_course_id,
                                      subpath='static',
                                      verbose=verbose)

            elif verbose and not do_import_static:
                log.debug(
                    "Skipping import of static content, "
                    "since do_import_static={0}".format(do_import_static))

            # no matter what do_import_static is, import "static_import" directory

            # This is needed because the "about" pages (eg "overview") are
            # loaded via load_extra_content, and do not inherit the lms
            # metadata from the course module, and thus do not get
            # "static_content_store" properly defined. Static content
            # referenced in those extra pages thus need to come through the
            # c4x:// contentstore, unfortunately. Tell users to copy that
            # content into the "static_import" subdir.

            simport = 'static_import'
            if os.path.exists(course_data_path / simport):
                import_static_content(course_data_path,
                                      static_content_store,
                                      dest_course_id,
                                      subpath=simport,
                                      verbose=verbose)

            # finally loop through all the modules
            for module in xml_module_store.modules[course_key].itervalues():
                if module.scope_ids.block_type == 'course':
                    # we've already saved the course module up at the top
                    # of the loop so just skip over it in the inner loop
                    continue

                if verbose:
                    log.debug('importing module location {loc}'.format(
                        loc=module.location))

                import_module(module,
                              store,
                              course_key,
                              dest_course_id,
                              do_import_static=do_import_static,
                              system=course.runtime)

            # now import any 'draft' items
            if draft_store is not None:
                import_course_draft(xml_module_store, store, draft_store,
                                    course_data_path, static_content_store,
                                    course_key, dest_course_id, course.runtime)

        finally:
            # turn back on all write signalling on stores that need it
            if (hasattr(store, 'ignore_write_events_on_courses') and
                    dest_course_id in store.ignore_write_events_on_courses):
                store.ignore_write_events_on_courses.remove(dest_course_id)
                store.refresh_cached_metadata_inheritance_tree(dest_course_id)

    return xml_module_store, course_items
コード例 #20
0
def _import_course_module(
        store, runtime, user_id, data_dir, course_key, dest_course_id, source_course, do_import_static,
        verbose,
):
    if verbose:
        log.debug("Scanning {0} for course module...".format(course_key))

    # Quick scan to get course module as we need some info from there.
    # Also we need to make sure that the course module is committed
    # first into the store
    course_data_path = path(data_dir) / source_course.data_dir

    log.debug(u'======> IMPORTING course {course_key}'.format(
        course_key=course_key,
    ))

    if not do_import_static:
        # for old-style xblock where this was actually linked to kvs
        source_course.static_asset_path = source_course.data_dir
        source_course.save()
        log.debug('course static_asset_path={path}'.format(
            path=source_course.static_asset_path
        ))

    log.debug('course data_dir={0}'.format(source_course.data_dir))

    with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, dest_course_id):

        course = _import_module_and_update_references(
            source_course, store, user_id,
            course_key,
            dest_course_id,
            do_import_static=do_import_static,
            runtime=runtime,
        )

        for entry in course.pdf_textbooks:
            for chapter in entry.get('chapters', []):
                if StaticContent.is_c4x_path(chapter.get('url', '')):
                    asset_key = StaticContent.get_location_from_path(chapter['url'])
                    chapter['url'] = StaticContent.get_static_path_from_location(asset_key)

        # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
        # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
        # values then remap it so that the wiki does not point to the old wiki.
        if course_key != course.id:
            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                course_key.org,
                course_key.course,
                course_key.run
            )
            if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == course_key.course:
                course.wiki_slug = u'{0}.{1}.{2}'.format(
                    course.id.org,
                    course.id.course,
                    course.id.run,
                )

        # cdodge: more hacks (what else). Seems like we have a
        # problem when importing a course (like 6.002) which
        # does not have any tabs defined in the policy file.
        # The import goes fine and then displays fine in LMS,
        # but if someone tries to add a new tab in the CMS, then
        # the LMS barfs because it expects that -- if there are
        # *any* tabs -- then there at least needs to be
        # some predefined ones
        if course.tabs is None or len(course.tabs) == 0:
            CourseTabList.initialize_default(course)

        store.update_item(course, user_id)
    return course, course_data_path
コード例 #21
0
ファイル: test_assets.py プロジェクト: taozeze/ANALYSE
    def test_static_url_generation(self):

        course_key = SlashSeparatedCourseKey('org', 'class', 'run')
        location = course_key.make_asset_key('asset', 'my_file_name.jpg')
        path = StaticContent.get_static_path_from_location(location)
        self.assertEquals(path, '/static/my_file_name.jpg')
コード例 #22
0
    def test_static_url_generation(self):

        course_key = SlashSeparatedCourseKey("org", "class", "run")
        location = course_key.make_asset_key("asset", "my_file_name.jpg")
        path = StaticContent.get_static_path_from_location(location)
        self.assertEquals(path, "/static/my_file_name.jpg")
コード例 #23
0
def import_from_xml(
        store, user_id, data_dir, course_dirs=None,
        default_class='xmodule.raw_module.RawDescriptor',
        load_error_modules=True, static_content_store=None,
        target_course_id=None, verbose=False,
        do_import_static=True, create_new_course_if_not_present=False):
    """
    Import the specified xml data_dir into the "store" modulestore,
    using org and course as the location org and course.

    course_dirs: If specified, the list of course_dirs to load. Otherwise, load
    all course dirs

    target_course_id is the CourseKey that all modules should be remapped to
    after import off disk. We do this remapping as a post-processing step
    because there's logic in the importing which expects a 'url_name' as an
    identifier to where things are on disk
    e.g. ../policies/<url_name>/policy.json as well as metadata keys in
    the policy.json. so we need to keep the original url_name during import

    :param do_import_static:
        if False, then static files are not imported into the static content
        store. This can be employed for courses which have substantial
        unchanging static content, which is to inefficient to import every
        time the course is loaded. Static content for some courses may also be
        served directly by nginx, instead of going through django.

    : create_new_course_if_not_present:
        If True, then a new course is created if it doesn't already exist.
        The check for existing courses is case-insensitive.
    """

    xml_module_store = XMLModuleStore(
        data_dir,
        default_class=default_class,
        course_dirs=course_dirs,
        load_error_modules=load_error_modules,
        xblock_mixins=store.xblock_mixins,
        xblock_select=store.xblock_select,
    )

    # If we're going to remap the course_id, then we can only do that with
    # a single course
    if target_course_id:
        assert(len(xml_module_store.modules) == 1)

    # NOTE: the XmlModuleStore does not implement get_items()
    # which would be a preferable means to enumerate the entire collection
    # of course modules. It will be left as a TBD to implement that
    # method on XmlModuleStore.
    course_items = []

    with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
        for course_key in xml_module_store.modules.keys():

            if target_course_id is not None:
                dest_course_id = target_course_id
            else:
                dest_course_id = course_key

            # Creates a new course if it doesn't already exist
            if create_new_course_if_not_present and not store.has_course(dest_course_id, ignore_case=True):
                try:
                    store.create_course(dest_course_id.org, dest_course_id.course, dest_course_id.run, user_id)
                except InvalidLocationError:
                    # course w/ same org and course exists
                    log.debug(
                        "Skipping import of course with id, {0},"
                        "since it collides with an existing one".format(dest_course_id)
                    )
                    continue

            with store.bulk_write_operations(dest_course_id):
                course_data_path = None

                if verbose:
                    log.debug("Scanning {0} for course module...".format(course_key))

                # Quick scan to get course module as we need some info from there.
                # Also we need to make sure that the course module is committed
                # first into the store
                for module in xml_module_store.modules[course_key].itervalues():
                    if module.scope_ids.block_type == 'course':
                        course_data_path = path(data_dir) / module.data_dir

                        log.debug(u'======> IMPORTING course {course_key}'.format(
                            course_key=course_key,
                        ))

                        if not do_import_static:
                            # for old-style xblock where this was actually linked to kvs
                            module.static_asset_path = module.data_dir
                            module.save()
                            log.debug('course static_asset_path={path}'.format(
                                path=module.static_asset_path
                            ))

                        log.debug('course data_dir={0}'.format(module.data_dir))

                        course = _import_module_and_update_references(
                            module, store, user_id,
                            course_key,
                            dest_course_id,
                            do_import_static=do_import_static
                        )

                        for entry in course.pdf_textbooks:
                            for chapter in entry.get('chapters', []):
                                if StaticContent.is_c4x_path(chapter.get('url', '')):
                                    asset_key = StaticContent.get_location_from_path(chapter['url'])
                                    chapter['url'] = StaticContent.get_static_path_from_location(asset_key)

                        # Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
                        # If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
                        # values then remap it so that the wiki does not point to the old wiki.
                        if course_key != course.id:
                            original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
                                course_key.org,
                                course_key.course,
                                course_key.run
                            )
                            if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == course_key.course:
                                course.wiki_slug = u'{0}.{1}.{2}'.format(
                                    course.id.org,
                                    course.id.course,
                                    course.id.run,
                                )

                        # cdodge: more hacks (what else). Seems like we have a
                        # problem when importing a course (like 6.002) which
                        # does not have any tabs defined in the policy file.
                        # The import goes fine and then displays fine in LMS,
                        # but if someone tries to add a new tab in the CMS, then
                        # the LMS barfs because it expects that -- if there are
                        # *any* tabs -- then there at least needs to be
                        # some predefined ones
                        if course.tabs is None or len(course.tabs) == 0:
                            CourseTabList.initialize_default(course)

                        store.update_item(course, user_id)

                        course_items.append(course)
                        break

                # TODO: shouldn't this raise an exception if course wasn't found?

                # then import all the static content
                if static_content_store is not None and do_import_static:
                    # first pass to find everything in /static/
                    import_static_content(
                        course_data_path, static_content_store,
                        dest_course_id, subpath='static', verbose=verbose
                    )

                elif verbose and not do_import_static:
                    log.debug(
                        "Skipping import of static content, "
                        "since do_import_static={0}".format(do_import_static)
                    )

                # no matter what do_import_static is, import "static_import" directory

                # This is needed because the "about" pages (eg "overview") are
                # loaded via load_extra_content, and do not inherit the lms
                # metadata from the course module, and thus do not get
                # "static_content_store" properly defined. Static content
                # referenced in those extra pages thus need to come through the
                # c4x:// contentstore, unfortunately. Tell users to copy that
                # content into the "static_import" subdir.

                simport = 'static_import'
                if os.path.exists(course_data_path / simport):
                    import_static_content(
                        course_data_path, static_content_store,
                        dest_course_id, subpath=simport, verbose=verbose
                    )

                # now loop through all the modules
                for module in xml_module_store.modules[course_key].itervalues():
                    if module.scope_ids.block_type == 'course':
                        # we've already saved the course module up at the top
                        # of the loop so just skip over it in the inner loop
                        continue

                    if verbose:
                        log.debug('importing module location {loc}'.format(
                            loc=module.location
                        ))

                    _import_module_and_update_references(
                        module, store,
                        user_id,
                        course_key,
                        dest_course_id,
                        do_import_static=do_import_static,
                        runtime=course.runtime
                    )

                # finally, publish the course
                store.publish(course.location, user_id)

                # now import any DRAFT items
                _import_course_draft(
                    xml_module_store,
                    store,
                    user_id,
                    course_data_path,
                    course_key,
                    dest_course_id,
                    course.runtime
                )

    return xml_module_store, course_items
コード例 #24
0
ファイル: test_assets.py プロジェクト: Cabris/edx-platform
 def test_static_url_generation(self):
     location = Location(['i4x', 'foo', 'bar', 'asset', 'my_file_name.jpg'])
     path = StaticContent.get_static_path_from_location(location)
     self.assertEquals(path, '/static/my_file_name.jpg')
コード例 #25
0
ファイル: assets.py プロジェクト: praveen-pal/edx-platform
def upload_asset(request, org, course, coursename):
    '''
    This method allows for POST uploading of files into the course asset
    library, which will be supported by GridFS in MongoDB.
    '''
    # construct a location from the passed in path
    location = get_location_and_verify_access(request, org, course, coursename)

    # Does the course actually exist?!? Get anything from it to prove its
    # existence
    try:
        modulestore().get_item(location)
    except:
        # no return it as a Bad Request response
        logging.error('Could not find course' + location)
        return HttpResponseBadRequest()

    if 'files[]' not in request.FILES:
        return HttpResponseBadRequest()

    # compute a 'filename' which is similar to the location formatting, we're
    # using the 'filename' nomenclature since we're using a FileSystem paradigm
    # here. We're just imposing the Location string formatting expectations to
    # keep things a bit more consistent
    upload_file = request.FILES['files[]']
    filename = upload_file.name
    mime_type = upload_file.content_type

    content_loc = StaticContent.compute_location(org, course, filename)

    chunked = upload_file.multiple_chunks()
    sc_partial = partial(StaticContent, content_loc, filename, mime_type)
    if chunked:
        content = sc_partial(upload_file.chunks())
        tempfile_path = upload_file.temporary_file_path()
    else:
        content = sc_partial(upload_file.read())
        tempfile_path = None

    thumbnail_content = None
    thumbnail_location = None

    # first let's see if a thumbnail can be created
    (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail(
            content,
            tempfile_path=tempfile_path
    )

    # delete cached thumbnail even if one couldn't be created this time (else
    # the old thumbnail will continue to show)
    del_cached_content(thumbnail_location)
    # now store thumbnail location only if we could create it
    if thumbnail_content is not None:
        content.thumbnail_location = thumbnail_location

    # then commit the content
    contentstore().save(content)
    del_cached_content(content.location)

    # readback the saved content - we need the database timestamp
    readback = contentstore().find(content.location)

    response_payload = {
            'displayname': content.name,
            'uploadDate': get_default_time_display(readback.last_modified_at),
            'url': StaticContent.get_url_path_from_location(content.location),
            'portable_url': StaticContent.get_static_path_from_location(content.location),
            'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location)
                if thumbnail_content is not None else None,
            'msg': 'Upload completed'
    }

    response = JsonResponse(response_payload)
    return response
コード例 #26
0
ファイル: test_assets.py プロジェクト: AlexxNica/edx-platform
    def test_static_url_generation(self):

        course_key = CourseLocator('org', 'class', 'run')
        location = course_key.make_asset_key('asset', 'my_file_name.jpg')
        path = StaticContent.get_static_path_from_location(location)
        self.assertEquals(path, '/static/my_file_name.jpg')
コード例 #27
0
ファイル: test_assets.py プロジェクト: skim-ks/edx-platform
 def test_static_url_generation(self):
     location = Location(['i4x', 'foo', 'bar', 'asset', 'my_file_name.jpg'])
     path = StaticContent.get_static_path_from_location(location)
     self.assertEquals(path, '/static/my_file_name.jpg')
コード例 #28
0
ファイル: assets.py プロジェクト: AzizYosofi/edx-platform
def upload_asset(request, org, course, coursename):
    '''
    This method allows for POST uploading of files into the course asset
    library, which will be supported by GridFS in MongoDB.
    '''
    # construct a location from the passed in path
    location = get_location_and_verify_access(request, org, course, coursename)

    # Does the course actually exist?!? Get anything from it to prove its
    # existence
    try:
        modulestore().get_item(location)
    except:
        # no return it as a Bad Request response
        logging.error('Could not find course' + location)
        return HttpResponseBadRequest()

    if 'file' not in request.FILES:
        return HttpResponseBadRequest()

    # compute a 'filename' which is similar to the location formatting, we're
    # using the 'filename' nomenclature since we're using a FileSystem paradigm
    # here. We're just imposing the Location string formatting expectations to
    # keep things a bit more consistent
    upload_file = request.FILES['file']
    filename = upload_file.name
    mime_type = upload_file.content_type

    content_loc = StaticContent.compute_location(org, course, filename)

    chunked = upload_file.multiple_chunks()
    sc_partial = partial(StaticContent, content_loc, filename, mime_type)
    if chunked:
        content = sc_partial(upload_file.chunks())
        tempfile_path = upload_file.temporary_file_path()
    else:
        content = sc_partial(upload_file.read())
        tempfile_path = None

    thumbnail_content = None
    thumbnail_location = None

    # first let's see if a thumbnail can be created
    (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail(
            content,
            tempfile_path=tempfile_path
    )

    # delete cached thumbnail even if one couldn't be created this time (else
    # the old thumbnail will continue to show)
    del_cached_content(thumbnail_location)
    # now store thumbnail location only if we could create it
    if thumbnail_content is not None:
        content.thumbnail_location = thumbnail_location

    # then commit the content
    contentstore().save(content)
    del_cached_content(content.location)

    # readback the saved content - we need the database timestamp
    readback = contentstore().find(content.location)

    response_payload = {
            'displayname': content.name,
            'uploadDate': get_default_time_display(readback.last_modified_at),
            'url': StaticContent.get_url_path_from_location(content.location),
            'portable_url': StaticContent.get_static_path_from_location(content.location),
            'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location)
                if thumbnail_content is not None else None,
            'msg': 'Upload completed'
    }

    response = JsonResponse(response_payload)
    return response