def get_page(self, submission_url=None): """ @param submission_url: the submission url where the service may return submissions @return: an ExercisePage object created from data retrieved from exercise service """ page = ExercisePage(self) page.content = self.exercise_page_content return page
def get_page(self, submission_url=None): """ @param submission_url: the submission url where the service may return submissions @return: an ExercisePage containing the exercise instructions and possibly a submit form """ page = ExercisePage(self) page.content = self.instructions # Adds the submission form to the content if there are files to be submitted. # A template is used to avoid hard-coded HTML here. if self.get_files_to_submit(): template = loader.get_template('exercise/_file_submit_form.html') context = Context({'files' : self.get_files_to_submit()}) page.content += template.render(context) return page
def view_exercise(request, exercise_id): """ 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 # TODO: an error report should be sent or logged page = ExercisePage(exercise=exercise) messages.error( request, _('Connecting to the exercise service failed: %s.') % str(e)) exercise_summary = ExerciseSummary(exercise, request.user) return render_to_response( "exercise/view_exercise.html", CourseContext(request, exercise=exercise, course_instance=exercise.course_module.course_instance, page=page, form=form, submissions=submissions, exercise_summary=exercise_summary))
def get_page(self, submission_url): """ Retrieves the page for this exercise from the exercise service. @param submission_url: the submission url where the service may return submissions @return: an ExercisePage object created from data retrieved from exercise service """ # Build the URL with a callback address, max points etc. url = self.build_service_url(submission_url) opener = urllib2.build_opener() page_content = opener.open(url, timeout=20).read() return ExercisePage(self, page_content)
def submit(self, submission): """ This method sends the given submission to the exercise service along with the files related to the submission. """ # Make sure that this is the correct exercise for the submission assert self.id == submission.exercise.id # Create an empty list for HTTP request parameters post_params = [] # Parameters are appended to the list as key, value tuples. # Using tuples makes it possible to add two values for the same key. for (key, value) in submission.submission_data: post_params.append((key, value)) # Collect file handles to a list, so that they can be closed after being used handles = [] # Then the files are appended as key, file handle tuples for submitted_file in submission.files.all(): param_name = submitted_file.param_name file_handle = open(submitted_file.file_object.path, "rb") post_params.append((param_name, file_handle)) handles.append(file_handle) # Build the service URL, which contains maximum points for this exercise # and a callback URL to which the service may return the grading url = self.build_service_url(submission.get_callback_url()) opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler) response_body = opener.open(url, post_params, timeout=50).read() # Close all opened file handles for file_handle in handles: file_handle.close() return ExercisePage(self, response_body)
def _handle_submission(request, exercise, students, form, submissions): """ This method takes care of saving a new_submission locally and sending it to an exercise service for assessment. @param request: HttpRequest from Django @param exercise: an instance of an exercise class this submission is for @param students: a QuerySet of UserProfile objects that are submitting the exercise @param form: an instance of a Form class or None if there are no questions for the exercise @param submissions: previous submissions for the submitting user to the same exercise """ new_submission = Submission.objects.create(exercise=exercise) new_submission.submitters = students # Save the POST parameters from the new_submission in # a list of tuples [(key1, value1), (key2, value2)]. # By using tuples inside lists we allow two parameters # with the same name, which is not possible with dicts. new_submission.submission_data = helpers.query_dict_to_list_of_tuples( request.POST) # Add all submitted files to the new submission as SubmittedFile objects new_submission.add_files(request.FILES) try: # Try submitting the submission to the exercise service. The submission # is done with a multipart POST request that contains all the files and # POST parameters sent by the user. response_page = new_submission.submit_to_service() except Exception, e: #raise e # TODO: Retrieving the grading failed. An error report should be sent # to administrators messages.error( request, _('Connecting to the assessment server failed! (%s)') % str(e)) response_page = ExercisePage(exercise)
def submit(self, submission): page = ExercisePage(self) page.content = self.submission_page_content page.is_accepted= True return page
def submit(self, submission): page = ExercisePage(self) page.content = self.submission_page_content page.is_accepted = True return page