Exemple #1
0
def plugin_renderers(user, some_model, view_name=None):
    """
    Builds the plugin renderers for a view.
    """
    profile = user.userprofile if user.is_authenticated() else None
    if isinstance(some_model, CourseInstance):
        return build_plugin_renderers(
            some_model.plugins.all(),
            view_name or "course_instance",
            user_profile=profile,
            course_instance=some_model,
        )
    if isinstance(some_model, BaseExercise):
        course_instance = some_model.course_instance
        return build_plugin_renderers(
            course_instance.plugins.all(),
            view_name or "exercise",
            user_profile=profile,
            exercise=some_model,
            course_instance=course_instance,
        )
    if isinstance(some_model, Submission):
        course_instance = some_model.exercise.course_instance
        return build_plugin_renderers(
            course_instance.plugins.all(),
            view_name or "submission",
            user_profile=profile,
            submission=some_model,
            exercise=some_model.exercise,
            course_instance=course_instance,
        )
    logger.warn("Unrecognized model type received for plugin_renderers tag: {}" \
                .format(str(type(some_model))))
    return []
Exemple #2
0
def plugin_renderers(user, some_model, view_name=None):
    """
    Builds the plugin renderers for a view.
    """
    if isinstance(some_model, CourseInstance):
        return build_plugin_renderers(
            some_model.plugins.all(),
            view_name or "course_instance",
            user_profile=user.userprofile,
            course_instance=some_model,
        )
    if isinstance(some_model, BaseExercise):
        course_instance = some_model.course_instance
        return build_plugin_renderers(
            course_instance.plugins.all(),
            view_name or "exercise",
            user_profile=user.userprofile,
            exercise=some_model,
            course_instance=course_instance,
        )
    if isinstance(some_model, Submission):
        course_instance = some_model.exercise.course_instance
        return build_plugin_renderers(
            course_instance.plugins.all(),
            view_name or "submission",
            user_profile=user.userprofile,
            submission=some_model,
            exercise=some_model.exercise,
            course_instance=course_instance,
        )
    logger.warn("Unrecognized model type received for plugin_renderers tag: {}" \
                .format(str(type(some_model))))
    return []
Exemple #3
0
 def test_plugin_builder_selections(self):
     renderers = build_plugin_renderers(self.instance.plugins, 'submission',
                                        course_instance=self.instance, course=self.course)
     self.assertEqual(len(renderers), 0)
     renderers = build_plugin_renderers(self.instance.plugins, 'exercise',
                                        course_instance=self.instance, course=self.course)
     self.assertEqual(len(renderers), 2)
     renderers = build_plugin_renderers(self.instance.plugins, 'course_instance',
                                        course_instance=self.instance, course=self.course)
     self.assertEqual(len(renderers), 2)
Exemple #4
0
def view_instance(request, course_url, instance_url):
    """ Renders a dashboard page for a course instance. A dashboard has a list
        of exercise rounds and exercises and plugins that may have been 
        installed on the course. Students also see a summary of their progress
        on the course dashboard.
        
        @param request: the Django HttpRequest object
        @param course_url: the url value of a Course object
        @param instance_url: the url value of a CourseInstance object """
    
    course_instance = _get_course_instance(course_url, instance_url)

    if not course_instance.is_visible_to(request.user.get_profile()):
        return HttpResponseForbidden("You are not allowed "
                                     "to access this view.")

    course_summary  = CourseSummary(course_instance, request.user)

    plugin_renderers = build_plugin_renderers(
        plugins = course_instance.plugins.all(),
        view_name = "course_instance",
        user_profile = request.user.get_profile(),
        course_instance = course_instance
    )
    
    return render_to_response("course/view_instance.html", 
                              CourseContext(request, 
                                            course_instance=course_instance, 
                                            course_summary=course_summary,
                                            plugin_renderers=plugin_renderers,
                                            ))
Exemple #5
0
def view_exercise(request, exercise_id, template="exercise/view_exercise.html"):
    """ 
    Displays a particular exercise. If the exercise is requested with a HTTP POST request, 
    the view will try to submit the exercise to the exercise service. 
    
    @param request: HttpRequest from Django
    @param exercise_id: the id of the exercise model to display 
    """

    # Load the exercise as an instance of its leaf class
    exercise            = get_object_or_404(BaseExercise, id=exercise_id).as_leaf_class()
    students            = StudentGroup.get_students_from_request(request)
    submissions         = exercise.get_submissions_for_student(request.user.get_profile())
    is_post             = request.method == "POST"
    
    is_allowed, issues  = exercise.is_submission_allowed(students)
    
    for error in issues:
       messages.warning(request, error)
    
    # FIXME: remove support for custom forms
    form = None
    
    if is_post and is_allowed:
        # This is a successful submission, so we handle submitting the form
        return _handle_submission(request, exercise, students, form, submissions)
    
    try:
        # Try retrieving the exercise page
        submission_url  = exercise.get_submission_url_for_students(students)
        page            = exercise.get_page(submission_url)
    
    except Exception as e:
        # Retrieving page failed, create an empty page and display an error
        page            = ExercisePage(exercise=exercise)
        messages.error( request, _('Connecting to the exercise service '
                                   'failed!'))
        logging.exception(e)
    
    exercise_summary    = ExerciseSummary(exercise, request.user)

    plugin_renderers = build_plugin_renderers(
        plugins=exercise.course_module.course_instance.plugins.all(),
        view_name="exercise",
        user_profile=request.user.get_profile(),
        exercise=exercise,
        course_instance=exercise.course_instance)

    return render_to_response(template,
                              CourseContext(request,
                                            exercise=exercise,
                                            course_instance=exercise.course_module.course_instance,
                                            page=page,
                                            form=form, 
                                            submissions=submissions,
                                            exercise_summary=exercise_summary,
                                            plugin_renderers=plugin_renderers
                                            ))
Exemple #6
0
def view_submission(request, submission_id):
    # Find all submissions for this user
    submission      = get_object_or_404(Submission, id=submission_id)

    if not request.user.get_profile() in submission.submitters.all():
        # Note that we do not want to use submission.check_user_permission here
        # because that would allow staff-like users access this view. However
        # staff-like users should use the
        # staff_views.inspect_exercise_submission instead because some of the
        # stuff in this view wouldn't make sense to a staff-like user.

        # TODO: Yet another repeation of this error (most of them are in
        # course.views)
        return HttpResponseForbidden("You are not allowed "
                                     "to access this view.")

    exercise        = submission.exercise
    submissions     = exercise.get_submissions_for_student(
                                                    request.user.get_profile())
    index           = 1 + list(submissions).index(submission)
    
    exercise_summary= ExerciseSummary(exercise, request.user)

    plugin_renderers = build_plugin_renderers(
        exercise.course_module.course_instance.plugins,
        "submission",
        submission=submission,
        exercise=exercise,
        course_instance=exercise.course_instance,
        user_profile=request.user.get_profile()
    )

    return render_to_response("exercise/view_submission.html",
                              CourseContext(request,
                                            submission=submission,
                                            exercise=submission.exercise,
                                            course_instance=exercise
                                            .course_module.course_instance,
                                            submissions=submissions,
                                            submission_number=index,
                                            exercise_summary=exercise_summary,
                                            plugin_renderers=plugin_renderers))
Exemple #7
0
 def test_rss_plugin(self):
     renderers = build_plugin_renderers(RSSPlugin.objects, 'course_instance',
                                        course_instance=self.instance, course=self.course)
     html = renderers[0].render()
Exemple #8
0
 def test_html_plugin(self):
     renderers = build_plugin_renderers(HTMLPlugin.objects, 'exercise',
                                        course_instance=self.instance, course=self.course)
     html = renderers[0].render()
     self.assertTrue(HTML_PLUGIN_CONTENT in html)
Exemple #9
0
 def test_iframe_plugin(self):
     renderers = build_plugin_renderers(ExternalIFramePlugin.objects, 'exercise',
                                        course_instance=self.instance, course=self.course)
     html = renderers[0].render()
     self.assertTrue(IFRAME_PLUGIN_ADDRESS in html)
Exemple #10
0
def view_instance(request, course_url, instance_url):
    """
    Renders the home page for a course instance showing the current student's
    progress on the course.

    On the page, all the exercises of the course instance are organized as a
    schedule. They are primarily organized in a list of course modules which
    are primarily ordered according to their closing times and secondarily to
    their opening times. Inside the course modules the exercises are ordered
    according to their order attribute but in the same time, they are also
    grouped to their categories.

    The home page also contains a summary of the student's progress for the
    whole course instance, course modules, categories and each exercise.
        
    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """
    
    course_instance = _get_course_instance(course_url, instance_url)
    user_profile = request.user.get_profile()

    if not course_instance.is_visible_to(user_profile):
        return HttpResponseForbidden("You are not allowed "
                                     "to access this view.")

    # In the following code, we are going to construct a special data structure
    # to be used in the view_instance.html. We refer to the structure as the
    # exercise_tree. The main idea is to provide all the data for the template
    # in a way that makes the template as simple as possible.
    #
    # This is how the structure should be used in the template:
    #
    #   {% for course_module, round_summary, uncategorized_exercise_level, category_level in exercise_tree %}
    #
    #       ...
    #
    #       {% for exercise, exercise_summary in uncategorized_exercise_level %}
    #           ...
    #       {% endfor %}
    #
    #       ...
    #
    #       {% for category, category_summary, categorized_exercise_level in category_level %}
    #
    #           ...
    #
    #           {% for exercise, exercise_summary in categorized_exercise_level %}
    #               ...
    #           {% endfor %}
    #
    #           ...
    #
    #       {% endfor %}
    #
    #       ...
    #
    #   {% endfor %}
    #
    # Notice that all the nodes of the tree are tuples (all the lists contain
    # tuples). The tuples are of course formatted the same way in a particular
    # tree level (list).
    #
    # The CourseModule objects are ordered chronologically. The exercises are
    # ordered by their order attribute. The order of the categories is
    # determined by the order of the exercises. For example, if the first two
    # exercises belong to category A and then the following two exercises
    # belong to category B, our list of categories will begin like [A, B, ...].
    # Note that the category A may be in the list later too if there is more
    # exercises that belong to the category A. For example, if the fifth
    # exercises would belong to category A, our list of categories would be
    # [A, B, A, ...].
    #
    # The view_instance.html template renders the CourseModules objects so that
    # in addition to the categorized exercise list, there is an additional
    # small list of hotlinks for the exercises. For this reason, the exercise
    # tree separates to two different list on the second level--the list
    # containing all the exercises of the CourseModule (for the hotlinks) and
    # the list containing the LearningObjectCategory objects. The latter of
    # these then has a third level which finally contains lists of exercises
    # (grouped by the LearningObjectCategory objects of their parent node that
    # is).
    #
    # Also notice the summaries in the tuples. Those alway correspond to the
    # main object of the tuple.
    #

    course_summary = UserCourseSummary(course_instance, request.user)

    visible_categories = LearningObjectCategory.objects.filter(
        course_instance=course_instance).exclude(hidden_to=user_profile)
    visible_exercises = (BaseExercise.objects.filter(
        course_module__course_instance=course_instance,
        category__in=visible_categories)
        .select_related("course_module", "category").order_by("order"))

    visible_exercises_by_course_modules = defaultdict(list)
    for exercise in visible_exercises:
        (visible_exercises_by_course_modules[exercise.course_module]
         .append(exercise))

    visible_exercises_by_course_modules = sorted(
        visible_exercises_by_course_modules.items(),
        key=lambda t: (t[0].closing_time, t[0].opening_time))

    exercise_tree = [
        (course_module,
         course_summary.get_exercise_round_summary(course_module),
         [(exercise, course_summary.get_exercise_summary(exercise))
          for exercise in exercises], [])
        for course_module, exercises in visible_exercises_by_course_modules]

    for course_module, round_summary, exercises_and_summaries,\
            exercise_tree_category_level in exercise_tree:
        for exercise, exercise_summary in exercises_and_summaries:
            if (len(exercise_tree_category_level) == 0
                    or exercise_tree_category_level[-1][0]
                    != exercise.category):
                exercise_tree_category_level.append(
                    (exercise.category,
                     course_summary.get_exercise_round_summary(
                         exercise.category),
                     []))
            exercise_tree_category_level[-1][2].append((exercise,
                                                        exercise_summary))

    # Finished constructing the exercise_tree.

    course_instance_max_points = BaseExercise.get_course_instance_max_points(
        course_instance)

    plugin_renderers = build_plugin_renderers(
        plugins=course_instance.plugins.all(),
        view_name="course_instance",
        user_profile=user_profile,
        course_instance=course_instance)
    
    return render_to_response("course/view_instance.html", 
                              CourseContext(request, 
                                            course_instance=course_instance, 
                                            course_summary=course_summary,
                                            plugin_renderers=plugin_renderers,
                                            exercise_tree=exercise_tree,
                                            course_instance_max_points=
                                            course_instance_max_points,
                                            ))