示例#1
0
def get_module_combinedopenended(request, course, location, isupload):
    location = course.location[0]+'://'+course.location[1]+'/'+course.location[2]+'/chapter/'+location
    section_descriptor = modulestore().get_instance(course.id, location, depth=None)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user, section_descriptor, depth=None)
    descriptor = modulestore().get_instance_items(course.id, location,'combinedopenended',depth=None)
    content = []
    
    for x in range(len(descriptor)):
        module = get_module_for_descriptor(request.user, request, descriptor[x][1], field_data_cache, course.id,
                                         position=None, wrap_xmodule_display=True, grade_bucket_type=None,
                                         static_asset_path='')
        con = module.runtime.render(module, None, 'student_view').content
        confirm = Get_confirm()
        confirm.feed(con)
        if confirm.score_urls[0] == 'correct' and confirm.state_urls[0] == 'done':
            #content.append(add_edit_tool(con,course,descriptor[x]))
            #import logging
            #log = logging.getLogger("tracking")
            #log.debug("descriptor_location===============================\n:"+str(con)+"\n===========================")
            #c_info = Get_combinedopenended_info()
            #c_info.feed(con)
            title, body = Get_combinedopenended_info(con)
            content.append(create_discussion(request, course, descriptor[x][1].location[4], location,{'title':title,'body':body}))

    return content
示例#2
0
def answer_problem(course, request, problem, score=1, max_value=1):
    """
    Records an answer for the given problem.

    Arguments:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be answered
        score (float): The new score for the problem
        max_value (float): The new maximum score for the problem
    """

    user = request.user
    grade_dict = {'value': score, 'max_value': max_value, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    module = get_module(
        user,
        request,
        problem.location,
        field_data_cache,
    )
    module.runtime.publish(problem, 'grade', grade_dict)
示例#3
0
    def _update_last_visited_module_id(self, request, course, module_key, modification_date):
        """
        Saves the module id if the found modification_date is less recent than the passed modification date
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        try:
            module_descriptor = modulestore().get_item(module_key)
        except ItemNotFoundError:
            return Response(errors.ERROR_INVALID_MODULE_ID, status=400)
        module = get_module_for_descriptor(
            request.user, request, module_descriptor, field_data_cache, course.id, course=course
        )

        if modification_date:
            key = KeyValueStore.Key(
                scope=Scope.user_state,
                user_id=request.user.id,
                block_scope_id=course.location,
                field_name='position'
            )
            original_store_date = field_data_cache.last_modified(key)
            if original_store_date is not None and modification_date < original_store_date:
                # old modification date so skip update
                return self._get_course_info(request, course)

        save_positions_recursively_up(request.user, request, field_data_cache, module, course=course)
        return self._get_course_info(request, course)
 def test_rerandomization_set(self):
     descriptor = ItemFactory.create(
         category='problem',
         data=self.problem_xml,
         display_name='Option Response Problem2',
         rerandomize='always',
     )
     location = descriptor.location
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.user,
         descriptor
     )
     module = render.get_module(
         self.user,
         self.request,
         location,
         field_data_cache,
     )
     result_fragment = module.render(STUDENT_VIEW)
     self.assertIn('Staff Analytics Info', result_fragment.content)
     self.assertIn(
         'The analytics cannot be displayed for this question as it uses randomization.',
         result_fragment.content
     )
    def test_repeated_course_module_instantiation(self, loops, default_store, course_depth):

        with modulestore().default_store(default_store):
            course = CourseFactory.create()
            chapter = ItemFactory(parent=course, category='chapter', graded=True)
            section = ItemFactory(parent=chapter, category='sequential')
            __ = ItemFactory(parent=section, category='problem')

        fake_request = self.factory.get(
            reverse('progress', kwargs={'course_id': unicode(course.id)})
        )

        course = modulestore().get_course(course.id, depth=course_depth)

        for _ in xrange(loops):
            field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                course.id, self.user, course, depth=course_depth
            )
            course_module = get_module_for_descriptor(
                self.user,
                fake_request,
                course,
                field_data_cache,
                course.id,
                course=course
            )
            for chapter in course_module.get_children():
                for section in chapter.get_children():
                    for item in section.get_children():
                        self.assertTrue(item.graded)
    def test_toc_toy_from_section(self):
        chapter = 'Overview'
        chapter_url = '%s/%s/%s' % ('/courses', self.course_name, chapter)
        section = 'Welcome'
        factory = RequestFactory()
        request = factory.get(chapter_url)
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.toy_course.id, self.portal_user, self.toy_course, depth=2)

        expected = ([{'active': True, 'sections':
                      [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True,
                        'format': u'Lecture Sequence', 'due': None, 'active': False},
                       {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True,
                        'format': '', 'due': None, 'active': True},
                       {'url_name': 'video_123456789012', 'display_name': 'Test Video', 'graded': True,
                        'format': '', 'due': None, 'active': False},
                       {'url_name': 'video_4f66f493ac8f', 'display_name': 'Video', 'graded': True,
                        'format': '', 'due': None, 'active': False}],
                      'url_name': 'Overview', 'display_name': u'Overview'},
                     {'active': False, 'sections':
                      [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True,
                        'format': '', 'due': None, 'active': False}],
                      'url_name': 'secret:magic', 'display_name': 'secret:magic'}])

        actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section, field_data_cache)
        for toc_section in expected:
            self.assertIn(toc_section, actual)
示例#7
0
def check_for_active_timelimit_module(request, course_id, course):
    """
    Looks for a timing module for the given user and course that is currently active.
    If found, returns a context dict with timer-related values to enable display of time remaining.
    """
    context = {}

    # TODO (cpennington): Once we can query the course structure, replace this with such a query
    timelimit_student_modules = StudentModule.objects.filter(student=request.user, course_id=course_id, module_type='timelimit')
    if timelimit_student_modules:
        for timelimit_student_module in timelimit_student_modules:
            # get the corresponding section_descriptor for the given StudentModel entry:
            module_state_key = timelimit_student_module.module_state_key
            timelimit_descriptor = modulestore().get_instance(course_id, Location(module_state_key))
            timelimit_module_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user,
                                                                                     timelimit_descriptor, depth=None)
            timelimit_module = get_module_for_descriptor(request.user, request, timelimit_descriptor,
                                                         timelimit_module_cache, course.id, position=None)
            if timelimit_module is not None and timelimit_module.category == 'timelimit' and \
                    timelimit_module.has_begun and not timelimit_module.has_ended:
                location = timelimit_module.location
                # determine where to go when the timer expires:
                if timelimit_descriptor.time_expired_redirect_url is None:
                    raise Http404("no time_expired_redirect_url specified at this location: {} ".format(timelimit_module.location))
                context['time_expired_redirect_url'] = timelimit_descriptor.time_expired_redirect_url
                # Fetch the remaining time relative to the end time as stored in the module when it was started.
                # This value should be in milliseconds.
                remaining_time = timelimit_module.get_remaining_time_in_ms()
                context['timer_expiration_duration'] = remaining_time
                context['suppress_toplevel_navigation'] = timelimit_descriptor.suppress_toplevel_navigation
                return_url = reverse('jump_to', kwargs={'course_id': course_id, 'location': location})
                context['timer_navigation_return_url'] = return_url
    return context
示例#8
0
    def test_entrance_exam_passed_message_and_course_content(self):
        """
        Unit Test: exam passing message and rest of the course section should be present
        when user achieves the entrance exam milestone/pass the exam.
        """
        url = reverse(
            'courseware_section',
            kwargs={
                'course_id': unicode(self.course.id),
                'chapter': self.entrance_exam.location.name,
                'section': self.exam_1.location.name
            }
        )

        # 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)

        resp = self.client.get(url)
        self.assertNotIn('To access course materials, you must score', resp.content)
        self.assertIn('You have passed the entrance exam.', resp.content)
        self.assertIn('Lesson 1', resp.content)
    def _get_module(self, course_id, descriptor, location):
        """
        Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, self.staff_user, descriptor)

        return render.get_module(self.staff_user, self.request, location, field_data_cache)
示例#10
0
def _get_module_instance_for_task(course_id, student, module_descriptor, xmodule_instance_args=None,
                                  grade_bucket_type=None):
    """
    Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`.

    `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback.
    These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps
    the need for a Request object when instantiating an xmodule instance.
    """
    # reconstitute the problem's corresponding XModule:
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, module_descriptor)

    # get request-related tracking information from args passthrough, and supplement with task-specific
    # information:
    request_info = xmodule_instance_args.get('request_info', {}) if xmodule_instance_args is not None else {}
    task_info = {"student": student.username, "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args)}

    def make_track_function():
        '''
        Make a tracking function that logs what happened.

        For insertion into ModuleSystem, and used by CapaModule, which will
        provide the event_type (as string) and event (as dict) as arguments.
        The request_info and task_info (and page) are provided here.
        '''
        return lambda event_type, event: task_track(request_info, task_info, event_type, event, page='x_module_task')

    xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \
        if xmodule_instance_args is not None else ''

    return get_module_for_descriptor_internal(student, module_descriptor, field_data_cache, course_id,
                                              make_track_function(), xqueue_callback_url_prefix,
                                              grade_bucket_type=grade_bucket_type)
    def test_module_render_with_jump_to_id(self):
        """
        This test validates that the /jump_to_id/<id> shorthand for intracourse linking works assertIn
        expected. Note there's a HTML element in the 'toy' course with the url_name 'toyjumpto' which
        defines this linkage
        """
        mock_request = MagicMock()
        mock_request.user = self.mock_user

        course = get_course_with_access(self.mock_user, self.course_id, 'load')

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_id, self.mock_user, course, depth=2)

        module = render.get_module(
            self.mock_user,
            mock_request,
            Location('i4x', 'edX', 'toy', 'html', 'toyjumpto'),
            field_data_cache,
            self.course_id
        )

        # get the rendered HTML output which should have the rewritten link
        html = module.render('student_view').content

        # See if the url got rewritten to the target link
        # note if the URL mapping changes then this assertion will break
        self.assertIn('/courses/' + self.course_id + '/jump_to_id/vertical_test', html)
    def setUp(self):
        self.user = UserFactory.create()
        self.request = RequestFactory().get('/')
        self.request.user = self.user
        self.request.session = {}
        self.course = CourseFactory.create()

        problem_xml = OptionResponseXMLFactory().build_xml(
            question_text='The correct answer is Correct',
            num_inputs=2,
            weight=2,
            options=['Correct', 'Incorrect'],
            correct_option='Correct'
        )
        self.descriptor = ItemFactory.create(
            category='problem',
            data=problem_xml,
            display_name='Option Response Problem'
        )

        self.location = self.descriptor.location
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            self.user,
            self.descriptor
        )
示例#13
0
    def _update_last_visited_sequential(self, request, course, chapter_id, sequential_id, modification_date):
        '''
        course -- xmodule
        '''
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        try:
            chapter_descriptor = get_item(course.id, 'chapter', chapter_id)
            sequential_descriptor = get_item(course.id, 'sequential', sequential_id)
        except ItemNotFoundError:
            raise error.Error(status=status.HTTP_404_NOT_FOUND)
        course_descriptor = course
        course = get_module_for_descriptor(
                request.user, request, course_descriptor, field_data_cache, course.id)
        chapter = get_module_for_descriptor(
                request.user, request, chapter_descriptor, field_data_cache, course.id)
        sequential = get_module_for_descriptor(
                request.user, request, sequential_descriptor, field_data_cache, course.id)
        if modification_date:
            key = KeyValueStore.Key(
                scope=Scope.user_state,
                user_id=request.user.id,
                block_scope_id=course.location,
                field_name=None
            )
            student_module = field_data_cache.find(key)
            if student_module:
                original_store_date = student_module.modified
                if modification_date < original_store_date:
                    # old modification date so skip update
                    return self._get_course_info(request, course)

        self.save_sequential_position(course, chapter, sequential)
        return self._get_course_info(request, course)
def student_course_progress(request, course_id, username):
    from django.contrib.auth.models import User
    from courseware.model_data import FieldDataCache
    from courseware import grades
    from django.http import Http404, HttpResponse, HttpResponseRedirect

    student=User.objects.filter(username=username)
    
    if not student.exists():
        return HttpResponse("Student '%s' not exists." % username)

    student=student[0]

    #return HttpResponse(request.session)

    try:
        course=get_course_by_id(course_id)
    except:
        return HttpResponse("Course '%s' not exists." % course_id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None)
    grade_summary = grades.grade(student, request, course, field_data_cache)
    progress="{totalscore:.0%}".format(totalscore=grade_summary['percent'])

    return HttpResponse("course:%s<br>user:%s<br>progress:%s" % (course_id,username,progress))
示例#15
0
    def test_entrance_exam_score(self):
        """
        test entrance exam score. we will hit the method get_entrance_exam_score to verify exam score.
        """
        exam_score = get_entrance_exam_score(self.request, self.course)
        self.assertEqual(exam_score, 0)

        # Pass the entrance exam
        # pylint: disable=maybe-no-member,no-member
        grade_dict = {'value': 1, 'max_value': 2, '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)

        exam_score = get_entrance_exam_score(self.request, self.course)
        # 50 percent exam score should be achieved.
        self.assertEqual(exam_score * 100, 50)
示例#16
0
def edxnotes(request, course_id):
    """
    Displays the EdxNotes page.
    """
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)

    if not is_feature_enabled(course):
        raise Http404

    try:
        notes = get_notes(request.user, course)
    except EdxNotesServiceUnavailable:
        raise Http404

    context = {
        "course": course,
        "search_endpoint": reverse("search_notes", kwargs={"course_id": course_id}),
        "notes": notes,
        "debug": json.dumps(settings.DEBUG),
        'position': None,
    }

    if not notes:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2
        )
        course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course_key)
        position = get_course_position(course_module)
        if position:
            context.update({
                'position': position,
            })

    return render_to_response("edxnotes/edxnotes.html", context)
示例#17
0
    def list(self, request, course, return_blocks=True, return_nav=True, *args, **kwargs):
        """
        REST API endpoint for listing all the blocks and/or navigation information in the course,
        while regarding user access and roles.

        Arguments:
            request - Django request object
            course - course module object
            return_blocks - If true, returns the blocks information for the course.
            return_nav - If true, returns the navigation information for the course.
        """
        # set starting point
        start_block = course

        # initialize request and result objects
        request_info = self.RequestInfo(request, course)
        result_data = self.ResultData(return_blocks, return_nav)

        # create and populate a field data cache by pre-fetching for the course (with depth=None)
        request_info.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=None,
        )

        # start the recursion with the start_block
        self.recurse_blocks_nav(request_info, result_data, self.BlockInfo(start_block, request_info))

        # return response
        response = {"root": unicode(start_block.location)}
        result_data.update_response(response, return_blocks, return_nav)
        return Response(response)
示例#18
0
def answer_problem(course, request, problem, score=1, max_value=1):
    """
    Records a correct answer for the given problem.

    Arguments:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be answered
    """

    user = request.user
    grade_dict = {'value': score, 'max_value': max_value, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    # pylint: disable=protected-access
    module = get_module(
        user,
        request,
        problem.scope_ids.usage_id,
        field_data_cache,
    )._xmodule
    module.system.publish(problem, 'grade', grade_dict)
示例#19
0
def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_info=False, course=None):
    """
    Gets a module instance based on its `usage_id` in a course, for a given request/user

    Returns (instance, tracking_context)
    """
    user = request.user

    try:
        course_id = CourseKey.from_string(course_id)
        usage_key = UsageKey.from_string(unquote_slashes(usage_id)).map_into_course(course_id)
    except InvalidKeyError:
        raise Http404("Invalid location")

    try:
        descriptor = modulestore().get_item(usage_key)
        descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key)
    except ItemNotFoundError:
        log.warn(
            "Invalid location for course id %s: %s",
            usage_key.course_key,
            usage_key
        )
        raise Http404

    tracking_context = {
        'module': {
            'display_name': descriptor.display_name_with_default_escaped,
            'usage_key': unicode(descriptor.location),
        }
    }

    # For blocks that are inherited from a content library, we add some additional metadata:
    if descriptor_orig_usage_key is not None:
        tracking_context['module']['original_usage_key'] = unicode(descriptor_orig_usage_key)
        tracking_context['module']['original_usage_version'] = unicode(descriptor_orig_version)

    unused_masquerade, user = setup_masquerade(request, course_id, has_access(user, 'staff', descriptor, course_id))
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        descriptor,
        read_only=CrawlersConfig.is_crawler(request),
    )
    instance = get_module_for_descriptor(
        user,
        request,
        descriptor,
        field_data_cache,
        usage_key.course_key,
        disable_staff_debug_info=disable_staff_debug_info,
        course=course
    )
    if instance is None:
        # Either permissions just changed, or someone is trying to be clever
        # and load something they shouldn't have access to.
        log.debug("No module %s for user %s -- access denied?", usage_key, user)
        raise Http404

    return (instance, tracking_context)
示例#20
0
def get_static_tab_contents(request, course, tab):
    """
    Returns the contents for the given static tab
    """
    loc = Location(course.location.tag, course.location.org, course.location.course, tab.type, tab.url_slug)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, modulestore().get_instance(course.id, loc), depth=0
    )
    tab_module = get_module(
        request.user, request, loc, field_data_cache, course.id, static_asset_path=course.static_asset_path
    )

    logging.debug("course_module = {0}".format(tab_module))

    html = ""
    if tab_module is not None:
        try:
            html = tab_module.render("student_view").content
        except Exception:  # pylint: disable=broad-except
            html = render_to_string("courseware/error-message.html", None)
            log.exception(
                u"Error rendering course={course}, tab={tab_url}".format(course=course, tab_url=tab["url_slug"])
            )

    return html
示例#21
0
    def test_module_render_with_jump_to_id(self):
        """
        This test validates that the /jump_to_id/<id> shorthand for intracourse linking works assertIn
        expected. Note there's a HTML element in the 'toy' course with the url_name 'toyjumpto' which
        defines this linkage
        """
        mock_request = MagicMock()
        mock_request.user = self.mock_user

        course = get_course_with_access(self.mock_user, "load", self.course_key)

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_key, self.mock_user, course, depth=2
        )

        module = render.get_module(
            self.mock_user, mock_request, self.course_key.make_usage_key("html", "toyjumpto"), field_data_cache
        )

        # get the rendered HTML output which should have the rewritten link
        html = module.render(STUDENT_VIEW).content

        # See if the url got rewritten to the target link
        # note if the URL mapping changes then this assertion will break
        self.assertIn("/courses/" + self.course_key.to_deprecated_string() + "/jump_to_id/vertical_test", html)
示例#22
0
    def _iter_scorable_xmodules(block_structure):
        """
        Loop through all the blocks locators in the block structure, and retrieve
        the module (XModule or XBlock) associated with that locator.

        For implementation reasons, we need to pull the max_score from the
        XModule, even though the data is not user specific.  Here we bind the
        data to a SystemUser.
        """
        request = RequestFactory().get('/dummy-collect-max-grades')
        user = SystemUser()
        request.user = user
        request.session = {}
        root_block = block_structure.get_xblock(block_structure.root_block_usage_key)
        course_key = block_structure.root_block_usage_key.course_key
        cache = FieldDataCache.cache_for_descriptor_descendents(
            course_id=course_key,
            user=request.user,
            descriptor=root_block,
            descriptor_filter=lambda descriptor: descriptor.has_score,
        )
        for block_locator in block_structure.post_order_traversal():
            block = block_structure.get_xblock(block_locator)
            if getattr(block, 'has_score', False):
                module = get_module_for_descriptor(user, request, block, cache, course_key)
                yield module
示例#23
0
def answer_entrance_exam_problem(course, request, problem, user=None):
    """
    Takes a required milestone `problem` in a `course` and fulfills it.

    Args:
        course (Course): Course object, the course the required problem is in
        request (Request): request Object
        problem (xblock): xblock object, the problem to be fulfilled
        user (User): User object in case it is different from request.user
    """
    if not user:
        user = request.user

    grade_dict = {'value': 1, 'max_value': 1, 'user_id': user.id}
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=2
    )
    # pylint: disable=protected-access
    module = get_module(
        user,
        request,
        problem.scope_ids.usage_id,
        field_data_cache,
    )._xmodule
    module.system.publish(problem, 'grade', grade_dict)
示例#24
0
def get_static_tab_contents(request, course, tab):
    """
    Returns the contents for the given static tab
    """
    loc = course.id.make_usage_key(
        tab.type,
        tab.url_slug,
    )
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, modulestore().get_item(loc), depth=0
    )
    tab_module = get_module(
        request.user, request, loc, field_data_cache, static_asset_path=course.static_asset_path
    )

    logging.debug('course_module = {0}'.format(tab_module))

    html = ''
    if tab_module is not None:
        try:
            html = tab_module.render(STUDENT_VIEW).content
        except Exception:  # pylint: disable=broad-except
            html = render_to_string('courseware/error-message.html', None)
            log.exception(
                u"Error rendering course={course}, tab={tab_url}".format(course=course, tab_url=tab['url_slug'])
            )

    return html
示例#25
0
    def test_entrance_exam_content_info(self):
        """
        test entrance exam content info method
        """
        exam_chapter, is_exam_passed = get_entrance_exam_content_info(self.request, self.course)
        self.assertEqual(exam_chapter.url_name, self.entrance_exam.url_name)
        self.assertEqual(is_exam_passed, False)

        # Pass the entrance exam
        # 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)

        exam_chapter, is_exam_passed = get_entrance_exam_content_info(self.request, self.course)
        self.assertEqual(exam_chapter, None)
        self.assertEqual(is_exam_passed, True)
示例#26
0
def prep_course_for_grading(course, request):
    """Set up course module for overrides to function properly"""
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id, course=course)

    course._field_data_cache = {}  # pylint: disable=protected-access
    course.set_grading_policy(course.grading_policy)
    def rebind_noauth_module_to_user(module, real_user):
        """
        A function that allows a module to get re-bound to a real user if it was previously bound to an AnonymousUser.

        Will only work within a module bound to an AnonymousUser, e.g. one that's instantiated by the noauth_handler.

        Arguments:
            module (any xblock type):  the module to rebind
            real_user (django.contrib.auth.models.User):  the user to bind to

        Returns:
            nothing (but the side effect is that module is re-bound to real_user)
        """
        if user.is_authenticated():
            err_msg = ("rebind_noauth_module_to_user can only be called from a module bound to "
                       "an anonymous user")
            log.error(err_msg)
            raise LmsModuleRenderError(err_msg)

        field_data_cache_real_user = FieldDataCache.cache_for_descriptor_descendents(
            course_id,
            real_user,
            module.descriptor,
            asides=XBlockAsidesConfig.possible_asides(),
        )
        student_data_real_user = KvsFieldData(DjangoKeyValueStore(field_data_cache_real_user))

        (inner_system, inner_student_data) = get_module_system_for_user(
            user=real_user,
            student_data=student_data_real_user,  # These have implicit user bindings, rest of args considered not to
            descriptor=module.descriptor,
            course_id=course_id,
            track_function=track_function,
            xqueue_callback_url_prefix=xqueue_callback_url_prefix,
            position=position,
            wrap_xmodule_display=wrap_xmodule_display,
            grade_bucket_type=grade_bucket_type,
            static_asset_path=static_asset_path,
            user_location=user_location,
            request_token=request_token,
            course=course
        )

        module.descriptor.bind_for_student(
            inner_system,
            real_user.id,
            [
                partial(OverrideFieldData.wrap, real_user, course),
                partial(LmsFieldData, student_data=inner_student_data),
            ],
        )

        module.descriptor.scope_ids = (
            module.descriptor.scope_ids._replace(user_id=real_user.id)
        )
        module.scope_ids = module.descriptor.scope_ids  # this is needed b/c NamedTuples are immutable
        # now bind the module to the new ModuleSystem instance and vice-versa
        module.runtime = inner_system
        inner_system.xmodule_instance = module
def get_discussion_context(request, course, location, parent_location,portfolio_user):
        section_descriptor = modulestore().get_instance(course.id, parent_location, depth=None)
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course.id, portfolio_user, section_descriptor, depth=None)
        descriptor = modulestore().get_item(location)
        module = get_module_for_descriptor(portfolio_user, request, descriptor, field_data_cache, course.id,
                                     position=None, wrap_xmodule_display=True, grade_bucket_type=None,
                                     static_asset_path='')
        return module.runtime.render(module, None, 'student_view').content
示例#29
0
def get_course_lti_endpoints(request, course_id):
    """
    View that, given a course_id, returns the a JSON object that enumerates all of the LTI endpoints for that course.

    The LTI 2.0 result service spec at
    http://www.imsglobal.org/lti/ltiv2p0/uml/purl.imsglobal.org/vocab/lis/v2/outcomes/Result/service.html
    says "This specification document does not prescribe a method for discovering the endpoint URLs."  This view
    function implements one way of discovering these endpoints, returning a JSON array when accessed.

    Arguments:
        request (django request object):  the HTTP request object that triggered this view function
        course_id (unicode):  id associated with the course

    Returns:
        (django response object):  HTTP response.  404 if course is not found, otherwise 200 with JSON body.
    """
    try:
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    except InvalidKeyError:
        return HttpResponse(status=404)

    try:
        course = get_course(course_key, depth=2)
    except ValueError:
        return HttpResponse(status=404)

    anonymous_user = AnonymousUser()
    anonymous_user.known = False  # make these "noauth" requests like module_render.handle_xblock_callback_noauth
    lti_descriptors = modulestore().get_items(course.id, qualifiers={'category': 'lti'})

    lti_noauth_modules = [
        get_module_for_descriptor(
            anonymous_user,
            request,
            descriptor,
            FieldDataCache.cache_for_descriptor_descendents(
                course_key,
                anonymous_user,
                descriptor
            ),
            course_key
        )
        for descriptor in lti_descriptors
    ]

    endpoints = [
        {
            'display_name': module.display_name,
            'lti_2_0_result_service_json_endpoint': module.get_outcome_service_url(
                service_name='lti_2_0_result_rest_handler') + "/user/{anon_user_id}",
            'lti_1_1_result_service_xml_endpoint': module.get_outcome_service_url(
                service_name='grade_handler'),
        }
        for module in lti_noauth_modules
    ]

    return HttpResponse(json.dumps(endpoints), content_type='application/json')
示例#30
0
    def get_module_for_user(self, user):
        """Helper function to get useful module at self.location in self.course_id for user"""
        mock_request = MagicMock()
        mock_request.user = user
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(self.course.id, user, self.course, depth=2)

        return render.get_module(  # pylint: disable=protected-access
            user, mock_request, self.lti.location, field_data_cache
        )._xmodule
示例#31
0
def get_course_lti_endpoints(request, course_id):
    """
    View that, given a course_id, returns the a JSON object that enumerates all of the LTI endpoints for that course.

    The LTI 2.0 result service spec at
    http://www.imsglobal.org/lti/ltiv2p0/uml/purl.imsglobal.org/vocab/lis/v2/outcomes/Result/service.html
    says "This specification document does not prescribe a method for discovering the endpoint URLs."  This view
    function implements one way of discovering these endpoints, returning a JSON array when accessed.

    Arguments:
        request (django request object):  the HTTP request object that triggered this view function
        course_id (unicode):  id associated with the course

    Returns:
        (django response object):  HTTP response.  404 if course is not found, otherwise 200 with JSON body.
    """
    try:
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    except InvalidKeyError:
        return HttpResponse(status=404)

    try:
        course = get_course(course_key, depth=2)
    except ValueError:
        return HttpResponse(status=404)

    anonymous_user = AnonymousUser()
    anonymous_user.known = False  # make these "noauth" requests like module_render.handle_xblock_callback_noauth
    lti_descriptors = modulestore().get_items(course.id,
                                              qualifiers={'category': 'lti'})

    lti_noauth_modules = [
        get_module_for_descriptor(
            anonymous_user, request, descriptor,
            FieldDataCache.cache_for_descriptor_descendents(
                course_key, anonymous_user, descriptor), course_key)
        for descriptor in lti_descriptors
    ]

    endpoints = [{
        'display_name':
        module.display_name,
        'lti_2_0_result_service_json_endpoint':
        module.get_outcome_service_url(
            service_name='lti_2_0_result_rest_handler') +
        "/user/{anon_user_id}",
        'lti_1_1_result_service_xml_endpoint':
        module.get_outcome_service_url(service_name='grade_handler'),
    } for module in lti_noauth_modules]

    return HttpResponse(json.dumps(endpoints), content_type='application/json')
示例#32
0
    def rebind_noauth_module_to_user(module, real_user):
        """
        A function that allows a module to get re-bound to a real user if it was previously bound to an AnonymousUser.

        Will only work within a module bound to an AnonymousUser, e.g. one that's instantiated by the noauth_handler.

        Arguments:
            module (any xblock type):  the module to rebind
            real_user (django.contrib.auth.models.User):  the user to bind to

        Returns:
            nothing (but the side effect is that module is re-bound to real_user)
        """
        if user.is_authenticated():
            err_msg = (
                "rebind_noauth_module_to_user can only be called from a module bound to "
                "an anonymous user")
            log.error(err_msg)
            raise LmsModuleRenderError(err_msg)

        field_data_cache_real_user = FieldDataCache.cache_for_descriptor_descendents(
            course_id,
            real_user,
            module.descriptor,
            asides=XBlockAsidesConfig.possible_asides(),
        )

        (inner_system, inner_student_data) = get_module_system_for_user(
            user=real_user,
            field_data_cache=
            field_data_cache_real_user,  # These have implicit user bindings, rest of args considered not to
            descriptor=module.descriptor,
            course_id=course_id,
            track_function=track_function,
            xqueue_callback_url_prefix=xqueue_callback_url_prefix,
            position=position,
            wrap_xmodule_display=wrap_xmodule_display,
            grade_bucket_type=grade_bucket_type,
            static_asset_path=static_asset_path,
            user_location=user_location,
            request_token=request_token)
        # rebinds module to a different student.  We'll change system, student_data, and scope_ids
        module.descriptor.bind_for_student(
            inner_system,
            LmsFieldData(module.descriptor._field_data, inner_student_data),  # pylint: disable=protected-access
            real_user.id,
        )
        module.scope_ids = module.descriptor.scope_ids  # this is needed b/c NamedTuples are immutable
        # now bind the module to the new ModuleSystem instance and vice-versa
        module.runtime = inner_system
        inner_system.xmodule_instance = module
示例#33
0
            def create_module(descriptor):
                '''creates an XModule instance given a descriptor'''
                with manual_transaction():
                    field_data_cache = FieldDataCache([descriptor], course.id,
                                                      student)

                # don't need tracking/xqueue but we have to pass something
                return get_module_for_descriptor_internal(
                    student, descriptor,
                    field_data_cache,
                    course.id,
                    track_function=noop_track_function,  # dummy
                    xqueue_callback_url_prefix='',  # dummy
                    request_token='')  # dummy
    def _get_module(self, course_id, descriptor, location):
        """
        Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons
        """
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course_id, self.staff_user, descriptor)

        return render.get_module(
            self.staff_user,
            self.request,
            location,
            field_data_cache,
            course_id,
        )
def _get_module_instance_for_task(course_id,
                                  student,
                                  module_descriptor,
                                  xmodule_instance_args=None,
                                  grade_bucket_type=None):
    """
    Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`.

    `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback.
    These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps
    the need for a Request object when instantiating an xmodule instance.
    """
    # reconstitute the problem's corresponding XModule:
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, module_descriptor)

    # get request-related tracking information from args passthrough, and supplement with task-specific
    # information:
    request_info = xmodule_instance_args.get(
        'request_info', {}) if xmodule_instance_args is not None else {}
    task_info = {
        "student": student.username,
        "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args)
    }

    def make_track_function():
        '''
        Make a tracking function that logs what happened.

        For insertion into ModuleSystem, and used by CapaModule, which will
        provide the event_type (as string) and event (as dict) as arguments.
        The request_info and task_info (and page) are provided here.
        '''
        return lambda event_type, event: task_track(
            request_info, task_info, event_type, event, page='x_module_task')

    xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \
        if xmodule_instance_args is not None else ''

    return get_module_for_descriptor_internal(
        user=student,
        descriptor=module_descriptor,
        field_data_cache=field_data_cache,
        course_id=course_id,
        track_function=make_track_function(),
        xqueue_callback_url_prefix=xqueue_callback_url_prefix,
        grade_bucket_type=grade_bucket_type,
        # This module isn't being used for front-end rendering
        request_token=None,
    )
示例#36
0
 def inner_get_module(descriptor):
     """
     Delegate to get_module_for_descriptor (imported here to avoid circular reference)
     """
     from courseware.module_render import get_module_for_descriptor
     field_data_cache = FieldDataCache([descriptor], course.id, request.user)
     return get_module_for_descriptor(
         request.user,
         request,
         descriptor,
         field_data_cache,
         course.id,
         course=course
     )
示例#37
0
 def setUp(self):
     student_module = StudentModuleFactory(
         state=json.dumps({
             'a_field': 'a_value',
             'b_field': 'b_value'
         }))
     self.user = student_module.student
     self.assertEqual(
         self.user.id,
         1)  # check our assumption hard-coded in the key functions above.
     self.field_data_cache = FieldDataCache(
         [mock_descriptor([mock_field(Scope.user_state, 'a_field')])],
         course_id, self.user)
     self.kvs = DjangoKeyValueStore(self.field_data_cache)
示例#38
0
def get_module_for_student(student, usage_key, request=None, course=None):
    """Return the module for the (student, location) using a DummyRequest."""
    if request is None:
        request = DummyRequest()
        request.user = student

    descriptor = modulestore().get_item(usage_key, depth=0)
    field_data_cache = FieldDataCache([descriptor], usage_key.course_key,
                                      student)
    return get_module(student,
                      request,
                      usage_key,
                      field_data_cache,
                      course=course)
示例#39
0
    def test_changing_position_works(self):
        # Make a mock FieldDataCache for this course, so we can get the course module
        mock_field_data_cache = FieldDataCache([self.course], self.course.id, self.student)
        course = get_module_for_descriptor(
            self.student,
            MagicMock(name='request'),
            self.course,
            mock_field_data_cache,
            self.course.id
        )

        # Now that we have the course, change the position and save, nothing should explode!
        course.position = 2
        course.save()
示例#40
0
 def setup_modulestore(self, default_ms, num_finds, num_sends):
     self.course_key = self.create_toy_course()
     self.chapter = 'Overview'
     chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter)
     factory = RequestFactory()
     self.request = factory.get(chapter_url)
     self.request.user = UserFactory()
     self.modulestore = self.store._get_modulestore_for_courseid(
         self.course_key)
     with self.modulestore.bulk_operations(self.course_key):
         with check_mongo_calls(num_finds, num_sends):
             self.toy_course = self.store.get_course(self.toy_loc, depth=2)
             self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
                 self.toy_loc, self.request.user, self.toy_course, depth=2)
示例#41
0
def mobi_course_action(request, course_id, action):
    try:
        course_id_bak = course_id.replace('.', '/')
        if action in ["updates", "handouts", "structure"]:
            user = request.user
            if not user:
                user = AnonymousUser()

            course = get_course_with_access(user, course_id_bak, 'load')
            registered = registered_for_course(course, user)

            if action == "updates" and registered:
                # course_updates = get_course_info_section(request, course, action)
                loc = Location(course.location.tag, course.location.org,
                               course.location.course, 'course_info', action)
                field_data_cache = FieldDataCache([], course.id, request.user)
                course_module = get_module(
                    user,
                    request,
                    loc,
                    field_data_cache,
                    course.id,
                    wrap_xmodule_display=False,
                    static_asset_path=course.static_asset_path)
                return JsonResponse({
                    'updates': [
                        item for item in course_module.items
                        if item["status"] != "deleted"
                    ]
                })
            elif action == "handouts" and registered:
                course_handouts = get_course_info_section(
                    request, course, action)
                return JsonResponse({"handouts": course_handouts})
            elif action == "structure":
                url_name = request.get_host(
                ) + '/m/courses/' + course_id_bak + '/courseware'
                return JsonResponse(
                    _course_json(course=course,
                                 course_id=course.location.course_id,
                                 url_name=url_name))
            else:
                raise Exception
        else:
            course = get_course_with_access(request.user, course_id_bak,
                                            'see_exists')
            return JsonResponse(mobi_course_info(request, course))
    except:
        return JsonResponse({"success": False, "errmsg": "access denied!"})
示例#42
0
def ccx_gradebook(request, course):
    """
    Show the gradebook for this CCX.
    """
    # Need course module for overrides to function properly
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course.id, request.user, course, depth=2)
    course = get_module_for_descriptor(request.user, request, course,
                                       field_data_cache, course.id)

    ccx = get_ccx_for_coach(course, request.user)
    with ccx_context(ccx):
        # The grading policy for the MOOC is probably already cached.  We need
        # to make sure we have the CCX grading policy loaded.
        course._field_data_cache = {}  # pylint: disable=protected-access
        course.set_grading_policy(course.grading_policy)

        enrolled_students = User.objects.filter(
            ccxmembership__ccx=ccx, ccxmembership__active=1).order_by(
                'username').select_related("profile")

        student_info = [{
            'username':
            student.username,
            'id':
            student.id,
            'email':
            student.email,
            'grade_summary':
            student_grades(student, request, course),
            'realname':
            student.profile.name,
        } for student in enrolled_students]

        return render_to_response(
            'courseware/gradebook.html', {
                'students':
                student_info,
                'course':
                course,
                'course_id':
                course.id,
                'staff_access':
                request.user.is_staff,
                'ordered_grades':
                sorted(course.grade_cutoffs.items(),
                       key=lambda i: i[1],
                       reverse=True),
            })
示例#43
0
def check_for_active_timelimit_module(request, course_id, course):
    """
    Looks for a timing module for the given user and course that is currently active.
    If found, returns a context dict with timer-related values to enable display of time remaining.
    """
    context = {}

    # TODO (cpennington): Once we can query the course structure, replace this with such a query
    timelimit_student_modules = StudentModule.objects.filter(
        student=request.user, course_id=course_id, module_type='timelimit')
    if timelimit_student_modules:
        for timelimit_student_module in timelimit_student_modules:
            # get the corresponding section_descriptor for the given StudentModel entry:
            module_state_key = timelimit_student_module.module_state_key
            timelimit_descriptor = modulestore().get_instance(
                course_id, Location(module_state_key))
            timelimit_module_cache = FieldDataCache.cache_for_descriptor_descendents(
                course.id, request.user, timelimit_descriptor, depth=None)
            timelimit_module = get_module_for_descriptor(
                request.user,
                request,
                timelimit_descriptor,
                timelimit_module_cache,
                course.id,
                position=None)
            if timelimit_module is not None and timelimit_module.category == 'timelimit' and \
                    timelimit_module.has_begun and not timelimit_module.has_ended:
                location = timelimit_module.location
                # determine where to go when the timer expires:
                if timelimit_descriptor.time_expired_redirect_url is None:
                    raise Http404(
                        "no time_expired_redirect_url specified at this location: {} "
                        .format(timelimit_module.location))
                context[
                    'time_expired_redirect_url'] = timelimit_descriptor.time_expired_redirect_url
                # Fetch the remaining time relative to the end time as stored in the module when it was started.
                # This value should be in milliseconds.
                remaining_time = timelimit_module.get_remaining_time_in_ms()
                context['timer_expiration_duration'] = remaining_time
                context[
                    'suppress_toplevel_navigation'] = timelimit_descriptor.suppress_toplevel_navigation
                return_url = reverse('jump_to',
                                     kwargs={
                                         'course_id': course_id,
                                         'location': location
                                     })
                context['timer_navigation_return_url'] = return_url
    return context
示例#44
0
def progress(request, course_id, student_id=None):
    """ User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user,
                                    course_id,
                                    'load',
                                    depth=None)
    staff_access = has_access(request.user, course, 'staff')

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, course, depth=None)

    courseware_summary = grades.progress_summary(student, request, course,
                                                 field_data_cache)
    grade_summary = grades.grade(student, request, course, field_data_cache)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        'course': course,
        'courseware_summary': courseware_summary,
        'grade_summary': grade_summary,
        'staff_access': staff_access,
        'student': student,
    }
    context.update()

    return render_to_response('courseware/progress.html', context)
示例#45
0
 def setUp(self):
     field_storage = self.factory.create()
     if hasattr(field_storage, 'student'):
         self.user = field_storage.student
     else:
         self.user = UserFactory.create()
     self.mock_descriptor = mock_descriptor([
         mock_field(self.scope, 'existing_field'),
         mock_field(self.scope, 'other_existing_field')
     ])
     # Each field is stored as a separate row in the table,
     # but we can query them in a single query
     with self.assertNumQueries(1):
         self.field_data_cache = FieldDataCache([self.mock_descriptor],
                                                course_id, self.user)
     self.kvs = DjangoKeyValueStore(self.field_data_cache)
示例#46
0
def field_data_cache_for_grading(course, user):
    """
    Given a CourseDescriptor and User, create the FieldDataCache for grading.

    This will generate a FieldDataCache that only loads state for those things
    that might possibly affect the grading process, and will ignore things like
    Videos.
    """
    descriptor_filter = partial(descriptor_affects_grading,
                                course.block_types_affecting_grading)
    return FieldDataCache.cache_for_descriptor_descendents(
        course.id,
        user,
        course,
        depth=None,
        descriptor_filter=descriptor_filter)
 def setUp(self):
     self.user = UserFactory.create()
     self.request = RequestFactory().get('/')
     self.request.user = self.user
     self.request.session = {}
     self.course = CourseFactory.create()
     self.content_string = '<p>This is the content<p>'
     self.rewrite_link = '<a href="/static/foo/content">Test rewrite</a>'
     self.rewrite_bad_link = '<img src="/static//file.jpg" />'
     self.course_link = '<a href="/course/bar/content">Test course rewrite</a>'
     self.descriptor = ItemFactory.create(
         category='html',
         data=self.content_string + self.rewrite_link +
         self.rewrite_bad_link + self.course_link)
     self.location = self.descriptor.location
     self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id, self.user, self.descriptor)
示例#48
0
def edxnotes(request, course_id):
    """
    Displays the EdxNotes page.

    Arguments:
        request: HTTP request object
        course_id: course id

    Returns:
        Rendered HTTP response.
    """
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)

    if not is_feature_enabled(course, request.user):
        raise Http404

    notes_info = get_notes(request, course)
    has_notes = (len(notes_info.get('results')) > 0)
    context = {
        "course": course,
        "notes_endpoint": reverse("notes", kwargs={"course_id": course_id}),
        "notes": notes_info,
        "page_size": DEFAULT_PAGE_SIZE,
        "debug": settings.DEBUG,
        'position': None,
        'disabled_tabs': settings.NOTES_DISABLED_TABS,
        'has_notes': has_notes,
    }

    if not has_notes:
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        course_module = get_module_for_descriptor(request.user,
                                                  request,
                                                  course,
                                                  field_data_cache,
                                                  course_key,
                                                  course=course)
        position = get_course_position(course_module)
        if position:
            context.update({
                'position': position,
            })

    return render_to_response("edxnotes/edxnotes.html", context)
示例#49
0
 def create_module(descriptor):
     """
     Factory method for creating and binding a module for the given descriptor.
     """
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course_id,
         self.request.user,
         descriptor,
         depth=0,
     )
     course = get_course_by_id(self.course_id)
     return get_module_for_descriptor(self.request.user,
                                      self.request,
                                      descriptor,
                                      field_data_cache,
                                      self.course_id,
                                      course=course)
示例#50
0
def find_target_student_module(request, user_id, course_id, mod_id):
    """
    Retrieve target StudentModule
    """
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        modulestore().get_instance(course_id, mod_id),
        depth=0,
        select_for_update=True
    )
    instance = get_module(user, request, mod_id, field_data_cache, course_id, grade_bucket_type='xqueue')
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(mod_id, user)
        log.debug(msg)
        raise Http404
    return instance
示例#51
0
    def test_histogram_enabled_for_unscored_xmodules(self):
        """Histograms should not display for xmodules which are not scored."""

        html_descriptor = ItemFactory.create(
            category='html', data='Here are some course details.')
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, self.user, self.descriptor)
        with patch(
                'xmodule_modifiers.grade_histogram') as mock_grade_histogram:
            mock_grade_histogram.return_value = []
            module = render.get_module(
                self.user,
                self.request,
                html_descriptor.location,
                field_data_cache,
            )
            module.render(STUDENT_VIEW)
            self.assertFalse(mock_grade_histogram.called)
    def test_entrance_exam_passed_message_and_course_content(self):
        """
        Unit Test: exam passing message and rest of the course section should be present
        when user achieves the entrance exam milestone/pass the exam.
        """
        url = reverse('courseware_section',
                      kwargs={
                          'course_id': unicode(self.course.id),
                          'chapter': self.entrance_exam.location.name,
                          'section': self.exam_1.location.name
                      })

        # 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)

        # pylint: disable=protected-access
        module = get_module(
            self.request.user,
            self.request,
            self.problem_2.scope_ids.usage_id,
            field_data_cache,
        )._xmodule
        module.system.publish(self.problem_2, 'grade', grade_dict)

        resp = self.client.get(url)
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            self.assertNotIn('To access course materials, you must score',
                             resp.content)
            self.assertIn('You have passed the entrance exam.', resp.content)
            self.assertIn('Lesson 1', resp.content)
示例#53
0
 def test_no_problems(self):
     descriptor = ItemFactory.create(
         category='html',
         display_name='HTML Component',
     )
     location = descriptor.location
     field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
         self.course.id,
         self.user,
         descriptor
     )
     module = render.get_module(
         self.user,
         self.request,
         location,
         field_data_cache,
     )
     result_fragment = module.render(STUDENT_VIEW)
     self.assertNotIn('Staff Analytics Info', result_fragment.content)
示例#54
0
    def test_event_publishing(self, block_type, mock_track_function):
        request = self.request_factory.get('')
        request.user = self.mock_user
        course = CourseFactory()
        descriptor = ItemFactory(category=block_type, parent=course)
        field_data_cache = FieldDataCache([course, descriptor], course.id,
                                          self.mock_user)  # pylint: disable=no-member
        block = render.get_module(self.mock_user, request, descriptor.location,
                                  field_data_cache)

        event_type = 'event_type'
        event = {'event': 'data'}

        block.runtime.publish(block, event_type, event)

        mock_track_function.assert_called_once_with(request)

        mock_track_function.return_value.assert_called_once_with(
            event_type, event)
示例#55
0
def yield_problems(request, course, student):
    """
    Return an iterator over capa_modules that this student has
    potentially answered.  (all that student has answered will definitely be in
    the list, but there may be others as well).
    """
    grading_context = course.grading_context

    descriptor_locations = (
        descriptor.location.url()
        for descriptor in grading_context['all_descriptors'])
    existing_student_modules = set(
        StudentModule.objects.filter(
            module_state_key__in=descriptor_locations).values_list(
                'module_state_key', flat=True))

    sections_to_list = []
    for _, sections in grading_context['graded_sections'].iteritems():
        for section in sections:

            section_descriptor = section['section_descriptor']

            # If the student hasn't seen a single problem in the section, skip it.
            for moduledescriptor in section['xmoduledescriptors']:
                if moduledescriptor.location.url() in existing_student_modules:
                    sections_to_list.append(section_descriptor)
                    break

    field_data_cache = FieldDataCache(sections_to_list, course.id, student)
    for section_descriptor in sections_to_list:
        section_module = get_module(student, request,
                                    section_descriptor.location,
                                    field_data_cache, course.id)
        if section_module is None:
            # student doesn't have access to this module, or something else
            # went wrong.
            # log.debug("couldn't get module for student {0} for section location {1}"
            #           .format(student.username, section_descriptor.location))
            continue

        for problem in yield_module_descendents(section_module):
            if isinstance(problem, CapaModule):
                yield problem
示例#56
0
    def setUp(self):
        super(TestStudentModuleStorage, self).setUp()
        student_module = StudentModuleFactory(
            state=json.dumps({
                'a_field': 'a_value',
                'b_field': 'b_value'
            }))
        self.user = student_module.student
        self.assertEqual(
            self.user.id,
            1)  # check our assumption hard-coded in the key functions above.

        # There should be only one query to load a single descriptor with a single user_state field
        with self.assertNumQueries(1):
            self.field_data_cache = FieldDataCache(
                [mock_descriptor([mock_field(Scope.user_state, 'a_field')])],
                course_id, self.user)

        self.kvs = DjangoKeyValueStore(self.field_data_cache)
    def test_get_entrance_exam_content(self):
        """
        test get entrance exam content method
        """
        exam_chapter = get_entrance_exam_content(self.request, self.course)
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            self.assertEqual(exam_chapter.url_name,
                             self.entrance_exam.url_name)
            self.assertFalse(
                user_has_passed_entrance_exam(self.request, self.course))

            # Pass the entrance exam
            # 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)

            # pylint: disable=protected-access
            module = get_module(
                self.request.user,
                self.request,
                self.problem_2.scope_ids.usage_id,
                field_data_cache,
            )._xmodule
            module.system.publish(self.problem_2, 'grade', grade_dict)

            exam_chapter = get_entrance_exam_content(self.request, self.course)
            self.assertEqual(exam_chapter, None)
            self.assertTrue(
                user_has_passed_entrance_exam(self.request, self.course))
示例#58
0
    def _prefetch_and_bind_course(self):
        """
        Prefetches all descendant data for the requested section and
        sets up the runtime, which binds the request user to the section.
        """
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course_key,
            self.effective_user,
            self.course,
            depth=CONTENT_DEPTH,
        )

        self.course = get_module_for_descriptor(
            self.effective_user,
            self.request,
            self.course,
            self.field_data_cache,
            self.course_key,
            course=self.course,
        )
示例#59
0
def find_target_student_module(request, user_id, course_id, mod_id):
    """
    Retrieve target StudentModule
    """
    course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    usage_key = course_id.make_usage_key_from_deprecated_string(mod_id)
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id,
        user,
        modulestore().get_item(usage_key),
        depth=0,
        select_for_update=True
    )
    instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='xqueue')
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(mod_id, user)
        log.debug(msg)
        raise Http404
    return instance
示例#60
0
def load_single_xblock(request, user_id, course_id, usage_key_string, course=None):
    """
    Load a single XBlock identified by usage_key_string.
    """
    usage_key = UsageKey.from_string(usage_key_string)
    course_key = CourseKey.from_string(course_id)
    usage_key = usage_key.map_into_course(course_key)
    user = User.objects.get(id=user_id)
    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_key,
        user,
        modulestore().get_item(usage_key),
        depth=0,
    )
    instance = get_module(user, request, usage_key, field_data_cache, grade_bucket_type='xqueue', course=course)
    if instance is None:
        msg = "No module {0} for user {1}--access denied?".format(usage_key_string, user)
        log.debug(msg)
        raise Http404
    return instance