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
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)
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)
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
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)
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 )
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))
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)
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)
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)
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)
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)
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
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)
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
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)
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
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)
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
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')
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
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')
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
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, )
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 )
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)
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)
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()
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)
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!"})
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), })
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
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)
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)
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)
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)
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)
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
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)
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)
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)
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
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))
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, )
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
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