def list_exercise_submissions(request, exercise_id): """ This view lists all submissions for a given exercise. The view can only be accessed by course staff, meaning the teachers and assistants of the course. @param exercise_id: the ID of the exercise which the submissions are for """ exercise = get_object_or_404(BaseExercise, id=exercise_id) has_permission = exercise.get_course_instance().is_staff( request.user.get_profile()) if not has_permission: return HttpResponseForbidden( "You are not allowed to access this view.") submissions = exercise.submissions.all() return render_to_response( "exercise/exercise_submissions.html", CourseContext( request, submissions=submissions, exercise=exercise, course_instance=exercise.course_module.course_instance, ))
def add_or_edit_assignment(request, module_id): """ This page can be used by teachers to add new modules and edit existing ones. @param request: the Django HttpRequest object """ course_module = CourseModule.objects.get(id=module_id) #course_books = [] assignment = None #retrieve books book = Books.objects.filter(courses=course_module.course_instance)[0] if Assignments.objects.filter(course_module=course_module).count()>0: assignment = get_object_or_404(Assignments, \ course_module=course_module) if request.method == "POST": form = AssignmentForm(request.POST, instance=assignment) if form.is_valid(): assignment = form.save() messages.success(request, \ _('The assignment module was saved successfully.')) else: if not assignment: assignment = Assignments(course_module = course_module, assignment_book = book) form = AssignmentForm(instance=assignment) return render_to_response("course/set_exercises.html", CourseContext(request, course_instance = \ course_module.course_instance, module=course_module, form=form, book_name = book.book_name ))
def class_students(request, module_id): """ View which aloow the instructor to edit student's information """ course_module = CourseModule.objects.get(id=module_id) course_books = [] course_books = list(Books.objects.filter(courses = \ course_module.course_instance)) book = course_books[0] qs0 = UserBook.objects.prefetch_related('user').filter(book = \ book).order_by('user__username') studentsFormSet = modelformset_factory(UserBook, form=StudentsForm, \ extra=0) if request.method == "POST": formset = studentsFormSet(request.POST, queryset = qs0) if formset.is_valid(): formset.save() messages.success(request, \ _('Students information were saved successfully.')) else: formset = studentsFormSet(queryset = qs0) return render_to_response("course/edit_students.html", CourseContext(request, \ course_instance=course_module.course_instance, module=course_module, formset=formset ))
def course_archive(request): """ Displays a course archive of all courses in the system. """ context = CourseContext(request) return render_to_response("course/archive.html", context)
def add_or_edit_exercise(request, module_id, exercise_id=None): """ This page can be used by teachers to add new exercises and edit existing ones. """ module = get_object_or_404(CourseModule, id=module_id) course_instance = module.course_instance has_permission = course_instance.is_teacher(request.user.get_profile()) if not has_permission: return HttpResponseForbidden( "You are not allowed to access this view.") if exercise_id != None: exercise = get_object_or_404(module.learning_objects, id=exercise_id).as_leaf_class() else: exercise = BaseExercise(course_module=module) if request.method == "POST": form = BaseExerciseForm(request.POST, instance=exercise) if form.is_valid(): exercise = form.save() messages.success(request, _('The exercise was saved successfully.')) else: form = BaseExerciseForm(instance=exercise) return render_to_response( "exercise/edit_exercise.html", CourseContext(request, course_instance=course_instance, exercise=exercise, form=form))
def delete_assignment(request, module_id): """ This page can be used by teachers to delete existing assignments. @param request: the Django HttpRequest object """ course_module = CourseModule.objects.get(id=module_id) assignment = None if Assignments.objects.filter(course_module = course_module).count()>0: assignment = Assignments.objects.filter(course_module=course_module)[0] #retrieve books book = Books.objects.filter(courses=course_module.course_instance)[0] #create redirection url that is the teachers' view next_url = "/course/%s/%s/teachers/" % ( \ course_module.course_instance.course.url, \ course_module.course_instance.url) if Assignments.objects.filter(course_module = course_module).count()>0: assignment = get_object_or_404(Assignments, course_module = \ course_module) if Assignments.objects.filter(assignment_book = book).count() == 1: messages.warning(request, \ _('There should be at least one assignment in the course.')) return HttpResponseRedirect(next_url) if request.method == "POST": form = DelAssignmentForm(request.POST, instance=assignment) if form.is_valid(): assignment.delete() course_module.delete() messages.success(request, \ _('The assignment module was deleted successfully.')) return HttpResponseRedirect(next_url) else: if assignment is not None: assignment.delete() if course_module is not None: course_module.delete() messages.success(request, \ _('The assignment module was deleted successfully.')) return HttpResponseRedirect(next_url) else: if not assignment: assignment = Assignments(course_module = course_module) form = DelAssignmentForm(instance=assignment) return render_to_response("opendsa/edit_assignments.html", CourseContext(request, course_instance = \ course_module.course_instance, \ module=course_module, \ form=form, \ ))
def view_course(request, course_url): """ Displays a page for the given course. The page consists of a list of course instances for the course. @param request: the Django HttpRequest object @param course_url: the url value of a Course object """ course = get_object_or_404(Course, url=course_url) context = CourseContext(request, course=course) return render_to_response("course/view.html", context)
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 submission_assessment(request, submission_id): """ This view is used for assessing the given exercise submission. When assessing, the teacher or assistant may write verbal feedback and give a numeric grade for the submission. @param submission_id: the ID of the submission to assess """ submission = get_object_or_404(Submission, id=submission_id) exercise = submission.exercise if exercise.allow_assistant_grading: # Both the teachers and assistants are allowed to assess has_permission = exercise.get_course_instance().is_staff( request.user.get_profile()) else: # Only teacher is allowed to assess has_permission = exercise.get_course_instance().is_teacher( request.user.get_profile()) if not has_permission: return HttpResponseForbidden( _("You are not allowed to access this view.")) form = SubmissionReviewForm() if request.method == "POST": form = SubmissionReviewForm(request.POST) if form.is_valid(): try: submission.set_points(form.cleaned_data["points"], exercise.max_points) submission.grader = request.user.get_profile() submission.feedback = form.cleaned_data["feedback"] submission.set_ready() submission.save() messages.success(request, _("The review was saved successfully.")) return redirect(inspect_exercise_submission, submission_id=submission.id) except: messages.error( request, _("Saving review failed. Check that the grade is within allowed boundaries." )) return render_to_response( "exercise/submission_assessment.html", CourseContext(request, course_instance=exercise.get_course_instance(), exercise=exercise, submission=submission, form=form))
def upload_accounts(request, module_id): """ Views responsible of creating students accounts the instructor upload his course roaster An email is sent to each student """ course_module = CourseModule.objects.get(id=module_id) book = Books.objects.filter(courses=course_module.course_instance)[0] form = None if request.method == 'POST': form = AccountsUploadForm(request.POST, request.FILES) #current_user = request.user if form.is_valid(): account_created = 0 #with open(request.FILES['classfile'], 'rb') as csvfile: csvfile = request.FILES['classfile'] listreader = csv.reader(csvfile.read().splitlines()) #, delimiter=',', quotechar='|') for row in listreader: username = row[0] email = row[1] password = id_generator() if User.objects.filter(username=username).count()==0: User.objects.create_user( username, email, password) account_created = account_created + 1 #send notification email subject = '[OpenDSA] account created' message = 'Your OpenDSA account has been created for the Book instance at %s.\n\n\n username: %s\n password:%s' %(book.book_url,username, password) send_mail(subject, message, '*****@*****.**', [email], fail_silently=False) messages.success(request, \ _('%s account(s) created successfully.' %account_created)) else: form = AccountsUploadForm() return render_to_response("opendsa/studentsupload.html", CourseContext(request, course_instance = \ course_module.course_instance, \ module=course_module, \ form=form, \ ))
def assistants_view(request, course_url, instance_url): """ This is the special page for the assistants on the given course instance. @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) has_permission = course_instance.is_staff(request.user.get_profile()) if not has_permission: return HttpResponseForbidden( _("You are not allowed to access this view.")) return render_to_response( "course/assistants_view.html", CourseContext(request, course_instance=course_instance))
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) course_summary = CourseSummary(course_instance, request.user) course_instance.plugins.all() return render_to_response( "course/view_instance.html", CourseContext(request, course_instance=course_instance, course_summary=course_summary))
def add_or_edit_module(request, course_url, instance_url, module_id=None): """ This page can be used by teachers to add new modules and edit existing ones. @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 @param module_id: The id of the module to edit. If not given, a new module is created. """ course_instance = _get_course_instance(course_url, instance_url) has_permission = course_instance.is_teacher(request.user.get_profile()) if not has_permission: return HttpResponseForbidden( "You are not allowed to access this view.") if module_id != None: module = get_object_or_404(CourseModule, id=module_id, course_instance=course_instance) else: module = CourseModule(course_instance=course_instance) if request.method == "POST": form = CourseModuleForm(request.POST, instance=module) if form.is_valid(): module = form.save() messages.success(request, _('The course module was saved successfully.')) next_url = "/course/%s/%s/teachers/" % (course_instance.course.url, course_instance.url) return HttpResponseRedirect(next_url) else: form = CourseModuleForm(instance=module) return render_to_response( "course/edit_module.html", CourseContext(request, course_instance=course_instance, module=module, form=form))
def create_accounts(request, module_id): """ Views responsible of creating students accounts An email is sent to the course teachers at the end of the process """ course_module = CourseModule.objects.get(id=module_id) form = None if request.method == 'POST': form = AccountsCreationForm(request.POST) current_user = request.user account_created = 0 roster = 'username,password\n' if form.is_valid(): for x in range(0, form.cleaned_data['account_number']): username = form.cleaned_data['account_prefix'] + str(x) password = id_generator() if User.objects.filter(username=username).count()==0: User.objects.create_user( username, '', password) account_created = account_created + 1 roster = roster + username + ',' + password + '\n' messages.success(request, \ _('%s account(s) created successfully. The roster has been emailed to %s.' %(account_created, current_user.email))) #send notification email subject = '[OpenDSA] Students accounts created' message = 'List of accounts created.\n\n\n\n' + roster send_mail(subject, message, '*****@*****.**', [current_user.email], fail_silently=False) else: form = AccountsCreationForm() return render_to_response("opendsa/studentsaccounts.html", CourseContext(request, course_instance = \ course_module.course_instance, \ module=course_module, \ form=form, \ ))
def view_instance_results(request, course_url, instance_url): """ Renders a results page for a course instance. The results contain individual scores for each student on 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) table = ResultTable(course_instance) table_html = loader.render_to_string("course/_results_table.html", {"result_table": table}) return render_to_response( "course/view_results.html", CourseContext(request, course_instance=course_instance, result_table=table, table_html=table_html))
def view_submission(request, submission_id): # Find all submissions for this user submission = get_object_or_404(Submission, id=submission_id) exercise = submission.exercise submissions = exercise.get_submissions_for_student( request.user.get_profile()) index = 1 + list(submissions).index(submission) # TODO: Check the user's permission to view this submission more elegantly assert submission.check_user_permission(request.user.get_profile()) exercise_summary = ExerciseSummary(exercise, request.user) 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))
def view_my_page(request, course_url, instance_url): """ Renders a personalized page for a student on the course. The page is intended to show how well the student is doing on the course and shortcuts to the latest submissions. @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) course_summary = CourseSummary(course_instance, request.user) submissions = request.user.get_profile().submissions.filter( exercise__course_module__course_instance=course_instance).order_by( "-id") return render_to_response( "course/view_my_page.html", CourseContext(request, course_instance=course_instance, course_summary=course_summary, submissions=submissions))
def inspect_exercise_submission(request, submission_id): """ This is the view for course personnel for inspecting and manually assessing exercise submissions. To access this view, the user must be either an assistant or a teacher on the course where the exercise is held on. @param submission_id: the ID of the submission to be inspected """ submission = get_object_or_404(Submission, id=submission_id) exercise = submission.exercise has_permission = exercise.get_course_instance().is_staff( request.user.get_profile()) if not has_permission: return HttpResponseForbidden( "You are not allowed to access this view.") return render_to_response( "exercise/inspect_submission.html", CourseContext(request, submission=submission, exercise=exercise, course_instance=exercise.get_course_instance()))
new_submission.delete() exercise_summary = ExerciseSummary(exercise, request.user) instance = exercise.course_module.course_instance # Add a message to the user's message queue messages.warning( request, _('The exercise could not be graded. Please check the page below for errors.' )) return render_to_response( "exercise/view_exercise.html", CourseContext(request, exercise=exercise, course_instance=instance, page=response_page, form=form, submissions=submissions, exercise_summary=exercise_summary)) @login_required def view_submission(request, submission_id): # Find all submissions for this user submission = get_object_or_404(Submission, id=submission_id) exercise = submission.exercise submissions = exercise.get_submissions_for_student( request.user.get_profile()) index = 1 + list(submissions).index(submission) # TODO: Check the user's permission to view this submission more elegantly