def post(self, request, *args, **kwargs): # Use form to parse and validate the request. form = SubmissionCreateAndReviewForm( request.POST, exercise=self.exercise, students_choices=self.instance.get_student_profiles()) if not form.is_valid(): messages.error( request, _("Invalid POST data:\n{error}").format( error="\n".join(extract_form_errors(form)))) return self.redirect(self.exercise.get_submission_list_url()) sub = Submission.objects.create(exercise=self.exercise) sub.submitters.set(form.cleaned_students) sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), self.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grader = self.profile sub.grading_time = timezone.now() sub.set_ready() sub.save() messages.success(request, _("New submission stored.")) return self.redirect(sub.get_absolute_url())
def create_submissions(instance, admin_profile, json_text): """ Batch creates submissions and feedback from formatted JSON. """ try: submissions_json = json.loads(json_text) except Exception as e: return [_("Failed to parse the JSON: {}").format(str(e))] if not "objects" in submissions_json: return [_('Missing JSON field: objects')] errors = [] validated_forms = [] count = 0 for submission_json in submissions_json["objects"]: count += 1 if not "exercise_id" in submission_json: errors.append( _('Missing field "exercise_id" in object {count:d}.')\ .format(count=count)) continue exercise = BaseExercise.objects.filter( id=submission_json["exercise_id"], course_module__course_instance=instance).first() if not exercise: errors.append( _('Unknown exercise_id {id:d} in object {count:d}.')\ .format(id=submission_json["exercise_id"], count=count)) continue # Use form to parse and validate object data. form = BatchSubmissionCreateAndReviewForm(submission_json, exercise=exercise) if form.is_valid(): validated_forms.append(form) else: errors.append( _('Invalid fields in object {count:d}: {error}')\ .format(count=count, error="\n".join(extract_form_errors(form)))) if not errors: for form in validated_forms: sub = Submission.objects.create(exercise=form.exercise) sub.submitters = form.cleaned_data.get("students") \ or (form.cleaned_data.get("students_by_student_id") or form.cleaned_data.get("students_by_email")) sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), sub.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grading_time = timezone.now() sub.grader = form.cleaned_data.get("grader") or admin_profile sub.set_ready() sub.save() return errors
def _post_async_submission(request, exercise, submission, errors=None): """ Creates or grades a submission. Required parameters in the request are points, max_points and feedback. If errors occur or submissions are no longer accepted, a dictionary with "success" is False and "errors" list will be returned. """ if not errors: errors = [] # The feedback field may contain null characters, which would invalidate # the form before its clean method is executed. So replace them beforehand. post_data = request.POST.copy() feedback = post_data.get('feedback') if feedback: post_data['feedback'] = feedback.replace('\x00', '\\x00') # Use form to parse and validate the request. form = SubmissionCallbackForm(post_data) errors.extend(extract_form_errors(form)) if not form.is_valid(): submission.feedback = _( "ERROR_ALERT_EXERCISE_ASSESSMENT_SERVICE_MALFUNCTIONING") submission.set_error() submission.save() if exercise.course_instance.visible_to_students: msg = "Exercise service returned with invalid grade request: {}"\ .format("\n".join(errors)) logger.error(msg, extra={"request": request}) email_course_error(request, exercise, msg, False) return {"success": False, "errors": errors} # Grade the submission. try: submission.set_points(form.cleaned_data["points"], form.cleaned_data["max_points"]) submission.feedback = form.cleaned_data["feedback"] submission.grading_data = post_data if form.cleaned_data["error"]: submission.set_error() else: submission.set_ready() submission.save() if form.cleaned_data["notify"]: Notification.send(None, submission) else: Notification.remove(submission) return {"success": True, "errors": []} # Produce error if something goes wrong during saving the points. except Exception as e: logger.exception("Unexpected error while saving grade" " for {} and submission id {:d}".format( str(exercise), submission.id)) return {"success": False, "errors": [repr(e)]}
def _post_async_submission(request, exercise, submission, errors=None): """ Creates or grades a submission. Required parameters in the request are points, max_points and feedback. If errors occur or submissions are no longer accepted, a dictionary with "success" is False and "errors" list will be returned. """ if not errors: errors = [] # Use form to parse and validate the request. form = SubmissionCallbackForm(request.POST) errors.extend(extract_form_errors(form)) if not form.is_valid(): submission.feedback = _( "<div class=\"alert alert-error\">\n" "<p>The exercise assessment service is malfunctioning. " "Staff has been notified.</p>\n" "<p>This submission is now marked as erroneous.</p>\n" "</div>") submission.set_error() submission.save() if exercise.course_instance.visible_to_students: msg = "Exercise service returned with invalid grade request: {}"\ .format("\n".join(errors)) logger.error(msg, extra={"request": request}) email_course_error(request, exercise, msg, False) return {"success": False, "errors": errors} # Grade the submission. try: submission.set_points(form.cleaned_data["points"], form.cleaned_data["max_points"]) submission.feedback = form.cleaned_data["feedback"] submission.grading_data = request.POST if form.cleaned_data["error"]: submission.set_error() else: submission.set_ready() submission.save() if form.cleaned_data["notify"]: Notification.send(None, submission) else: Notification.remove(submission) return {"success": True, "errors": []} # Produce error if something goes wrong during saving the points. except Exception as e: logger.exception("Unexpected error while saving grade" " for {} and submission id {:d}".format( str(exercise), submission.id)) return {"success": False, "errors": [repr(e)]}
def _post_async_submission(request, exercise, submission, students, errors): """ Creates or grades a submission. Required parameters in the request are points, max_points and feedback. If errors occur or submissions are no longer accepted, a dictionary with "success" is False and "errors" list will be returned. """ # Use form to parse and validate the request. form = SubmissionCallbackForm(request.POST) errors.extend(extract_form_errors(form)) if not form.is_valid(): submission.feedback = _( "<div class=\"alert alert-error\">\n" "<p>The exercise assessment service is malfunctioning. " "Staff has been notified.</p>\n" "<p>This submission is now marked as erroneous.</p>\n" "</div>") submission.set_error() submission.save() if exercise.course_instance.visible_to_students: msg = "Exercise service returned with invalid grade request: {}"\ .format("\n".join(errors)) logger.error(msg, extra={"request": request}) email_course_error(request, exercise, msg, False) return { "success": False, "errors": errors } # Grade the submission. try: submission.set_points(form.cleaned_data["points"], form.cleaned_data["max_points"]) submission.feedback = form.cleaned_data["feedback"] submission.grading_data = request.POST if form.cleaned_data["error"]: submission.set_error() else: submission.set_ready() submission.save() return { "success": True, "errors": [] } # Produce error if something goes wrong during saving the points. except Exception as e: logger.exception("Unexpected error while saving grade" " for {} and submission id {:d}".format(str(exercise), submission.id)); return { "success": False, "errors": [repr(e)] }
def create_submissions(instance, admin_profile, json_text): """ Batch creates submissions and feedback from formatted JSON. """ try: submissions_json = json.loads(json_text) except Exception as e: return [ _("Parsing the submission JSON raised an error '{error!s}'."). format(error=e) ] if isinstance(submissions_json, dict): if not "objects" in submissions_json: return [_('Missing JSON field: objects.')] submissions_json = submissions_json["objects"] if not isinstance(submissions_json, list): return [_("Invalid JSON. Expected list or list in objects field")] errors = [] validated_forms = [] count = 0 for submission_json in submissions_json: count += 1 if not "exercise_id" in submission_json: errors.append( _('Missing field "exercise_id" in object {count:d}.').format( count=count)) continue exercise = BaseExercise.objects.filter( id=submission_json["exercise_id"], course_module__course_instance=instance).first() if not exercise: errors.append( _('Unknown exercise_id {id:d} in object {count:d}.').format( id=submission_json["exercise_id"], count=count)) continue # Use form to parse and validate object data. form = BatchSubmissionCreateAndReviewForm(submission_json, exercise=exercise) if form.is_valid(): validated_forms.append(form) else: errors.append( _("Object number {ordinal:d} has invalid fields:\n {errors}"). format(ordinal=count, errors='\n '.join(extract_form_errors(form)))) if not errors: for form in validated_forms: sub = Submission.objects.create(exercise=form.exercise) sub.submitters = form.cleaned_students sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), sub.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grading_time = timezone.now() sub.grader = form.cleaned_data.get("grader") or admin_profile sub.set_ready() sub.save() return errors
def create_submissions(instance, admin_profile, json_text): """ Batch creates submissions and feedback from formatted JSON. """ try: submissions_json = json.loads(json_text) except Exception as e: return [format_lazy( _('EXCEPTION_PARSING_SUBMISSION_JSON -- {error!s}'), error=e, )] if isinstance(submissions_json, dict): if not "objects" in submissions_json: return [_('JSON_FIELD_MISSING_OBJECTS')] submissions_json = submissions_json["objects"] if not isinstance(submissions_json, list): return [_('JSON_INVALID_EXPECTED_LIST')] errors = [] validated_forms = [] count = 0 for submission_json in submissions_json: count += 1 if not "exercise_id" in submission_json: errors.append( format_lazy( _('JSON_ERROR_MISSING_FIELD_EXERCISE_ID -- {count:d}'), count=count, ) ) continue exercise = BaseExercise.objects.filter( id=submission_json["exercise_id"], course_module__course_instance=instance).first() if not exercise: errors.append( format_lazy( _('JSON_ERROR_UNKNOWN_EXERCISE_ID -- {id:d}, {count:d}'), id=submission_json["exercise_id"], count=count, ) ) continue # Use form to parse and validate object data. form = BatchSubmissionCreateAndReviewForm(submission_json, exercise=exercise) if form.is_valid(): validated_forms.append(form) else: errors.append( format_lazy( _('JSON_ERROR_OBJECT_INVALID_FIELDS -- {ordinal:d}, {errors}'), ordinal=count, errors='\n '.join(extract_form_errors(form)) ) ) if not errors: for form in validated_forms: sub = Submission.objects.create(exercise=form.exercise) sub.submitters.set(form.cleaned_students) sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), sub.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grading_time = timezone.now() sub.grader = form.cleaned_data.get("grader") or admin_profile sub.set_ready() sub.save() return errors
def post(self, request, *args, **kwargs): self.handle() self.error = False try: submissions_json = json.loads( request.POST.get("submissions_json", "{}")) except Exception as e: logger.exception( "Failed to parse submission batch JSON from user: %s", request.user.username) self.set_error( _("Failed to parse the JSON: {error}"), error=str(e)) if not self.error and not "objects" in submissions_json: self.set_error(_('Missing JSON field: objects')) validated_forms = [] if not self.error: count = 0 for submission_json in submissions_json["objects"]: count += 1 if not "exercise_id" in submission_json: self.set_error( _('Missing field "exercise_id" in object {count:d}.'), count=count) continue exercise = BaseExercise.objects.filter( id=submission_json["exercise_id"], course_module__course_instance=self.instance).first() if not exercise: self.set_error( _('Unknown exercise_id {id} in object {count:d}.'), count=count, id=submission_json["exercise_id"]) continue # Use form to parse and validate object data. form = BatchSubmissionCreateAndReviewForm(submission_json, exercise=exercise) if form.is_valid(): validated_forms.append(form) else: self.set_error( _('Invalid fields in object {count:d}: {error}'), count=count, error="\n".join(extract_form_errors(form))) if not self.error: for form in validated_forms: sub = Submission.objects.create(exercise=form.exercise) sub.submitters = form.cleaned_data.get("students") \ or form.cleaned_data.get("students_by_student_id") sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), sub.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grading_time = timezone.now() sub.grader = form.cleaned_data.get("grader") or self.profile sub.set_ready() sub.save() messages.success(request, _("New submissions stored.")) return self.response()
def create_submissions(instance, admin_profile, json_text): """ Batch creates submissions and feedback from formatted JSON. """ try: submissions_json = json.loads(json_text) except Exception as e: return [_("Parsing the submission JSON raised an error '{error!s}'.") .format(error=e)] if isinstance(submissions_json, dict): if not "objects" in submissions_json: return [_('Missing JSON field: objects.')] submissions_json = submissions_json["objects"] if not isinstance(submissions_json, list): return [_("Invalid JSON. Expected list or list in objects field")] errors = [] validated_forms = [] count = 0 for submission_json in submissions_json: count += 1 if not "exercise_id" in submission_json: errors.append( _('Missing field "exercise_id" in object {count:d}.') .format(count=count)) continue exercise = BaseExercise.objects.filter( id=submission_json["exercise_id"], course_module__course_instance=instance).first() if not exercise: errors.append( _('Unknown exercise_id {id:d} in object {count:d}.') .format(id=submission_json["exercise_id"], count=count)) continue # Use form to parse and validate object data. form = BatchSubmissionCreateAndReviewForm(submission_json, exercise=exercise) if form.is_valid(): validated_forms.append(form) else: errors.append( _("Object number {ordinal:d} has invalid fields:\n {errors}") .format(ordinal=count, errors='\n '.join(extract_form_errors(form)))) if not errors: for form in validated_forms: sub = Submission.objects.create(exercise=form.exercise) sub.submitters = form.cleaned_students sub.feedback = form.cleaned_data.get("feedback") sub.set_points(form.cleaned_data.get("points"), sub.exercise.max_points, no_penalties=True) sub.submission_time = form.cleaned_data.get("submission_time") sub.grading_time = timezone.now() sub.grader = form.cleaned_data.get("grader") or admin_profile sub.set_ready() sub.save() return errors