def grade(self, request, submission, no_penalties=False, url_name="exercise"): """ Loads the exercise feedback page. """ language = get_language() submission_url = update_url_params( api_reverse("submission-grader", kwargs={'submission_id': submission.id}), get_graderauth_submission_params(submission), ) url = self._build_service_url(language, request, submission.submitters.all(), submission.ordinal_number(), url_name, submission_url) try: return load_feedback_page(request, url, self, submission, no_penalties=no_penalties) except OSError as error: page = ExercisePage(self) msg = "Unable to grade the submission. %s: %s" % ( error.__class__.__name__, error) page.errors.append(msg) return page
def __init__(self, *args: Any, **kwargs: Any) -> None: self.instance = kwargs.pop('instance') super().__init__(*args, **kwargs) self.fields['user_profiles'].widget.search_api_url = api_reverse( "user-list") if self.instance.sis_id: self.fields['sis'] = forms.BooleanField( required=False, label=_('LABEL_ENROLL_FROM_SIS'), )
def __init__(self, *args: Any, **kwargs: Any) -> None: course_instance = kwargs.get('instance').exercise.course_instance super().__init__(*args, **kwargs) self.fields['submitters'].widget.search_api_url = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}, ) self.fields[ 'submitters'].queryset = course_instance.get_student_profiles() self.fields[ 'submitters'].initial_queryset = self.instance.submitters.all()
def __init__(self, *args, **kwargs): course_instance = kwargs.get('instance').exercise.course_instance super().__init__(*args, **kwargs) self.fields['submitters'].widget.attrs[ "data-search-api-url"] = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}) self.fields[ 'submitters'].queryset = course_instance.get_student_profiles() self.fields[ 'submitters'].initial_queryset = self.instance.submitters.all()
def __init__(self, service, user, instance, host, title, context_id=None, link_id=None, add=None): self.service = service course = instance.course # Context and resource parameters. context_id = context_id or (host + instance.get_absolute_url()) link_id = link_id or "aplus{:d}".format(service.pk) title = title or link_id student_id = self.external_student_id(user) # Determine user role. role = "Student" if course.is_teacher(user): role = "Instructor" elif instance.is_assistant(user): role = "TA,TeachingAssistant" self.parameters = add or {} self.parameters.update({ "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": link_id, "resource_link_title": title, # User. "user_id": student_id, "roles": role, "lis_person_name_full": "{} {}".format(user.first_name, user.last_name), "lis_person_name_given": user.first_name, "lis_person_name_family": user.last_name, "lis_person_contact_email_primary": user.email, # Selected course. "context_id": context_id, "context_title": course.name, "context_label": course.code, "launch_presentation_locale": get_language(), "tool_consumer_instance_guid": host + "/aplus", "tool_consumer_instance_name": "A+ LMS", }) if service.enable_api_access: self.parameters.update({ # FIXME: we need request or full host with protocol here! 'custom_context_api': '//' + host + api_reverse("course-detail", kwargs={'course_id': instance.id}), 'custom_context_api_id': str(instance.id), 'custom_user_api_token': user.userprofile.api_token, })
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['assistants'].initial_queryset = self.instance.assistants.all() self.fields['assistants'].widget.attrs["data-search-api-url"] = api_reverse("user-list") if self.instance and self.instance.visible_to_students: self.fields["url"].widget.attrs["readonly"] = "true" self.fields["url"].help_text = _("The URL identifier is locked " "while the course is visible to students.") self.fields["lifesupport_time"].help_text = _("Removes visibility " "of model answers for students.") self.fields["archive_time"].help_text = _("Removes possibility " "for students to return answers.")
def __init__(self, *args: Any, **kwargs: Any) -> None: course_instance = kwargs.pop('instance') super(DeadlineRuleDeviationForm, self).__init__(*args, **kwargs) self.fields["module"].queryset = CourseModule.objects.filter( course_instance=course_instance) self.fields["exercise"].queryset = BaseExercise.objects.filter( course_module__course_instance=course_instance) self.fields[ 'submitter'].queryset = course_instance.get_student_profiles() self.fields['submitter'].widget.search_api_url = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}, )
def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.fields['teachers'].initial = self.instance.teachers.all() self.fields['teachers'].initial_queryset = self.instance.teachers.all() self.fields['teachers'].widget.search_api_url = api_reverse( "user-list") self.fields['assistants'].initial = self.instance.assistants.all() self.fields[ 'assistants'].initial_queryset = self.instance.assistants.all() self.fields['assistants'].widget.search_api_url = api_reverse( "user-list") if self.instance and self.instance.visible_to_students: self.fields["url"].widget.attrs["readonly"] = "true" self.fields["url"].help_text = _( 'COURSE_URL_IDENTIFIER_LOCKED_WHILE_COURSE_VISIBLE') self.fields["lifesupport_time"].help_text = _( 'COURSE_REMOVES_MODEL_ANSWER_VISIBILITY_STUDENTS') self.fields["archive_time"].help_text = _( 'COURSE_REMOVES_SUBMISSION_POSSIBILITY_STUDENTS') # If course is not connected to SIS system, disable the enroll checkbox if not self.instance.sis_id: self.fields['sis_enroll'].disabled = True
def __init__(self, *args, **kwargs): course_instance = kwargs.get('instance').course_instance super().__init__(*args, **kwargs) self.fields['members'].widget.attrs[ "data-search-api-url"] = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}) self.fields["members"].queryset = course_instance.get_student_profiles( ) # Course staff may use this form for modifying and creating student groups. # If an existing group is being modified, its current members must be # set to the initial queryset. if self.instance.id: self.fields[ "members"].initial_queryset = self.instance.members.all()
def grade(self, request, submission, no_penalties=False, url_name="exercise"): """ Loads the exercise feedback page. """ language = get_language() submission_url = update_url_params( api_reverse("submission-grader", kwargs={ 'submission_id': submission.id }), get_graderauth_submission_params(submission), ) url = self._build_service_url( language, request, submission.submitters.all(), submission.ordinal_number(), url_name, submission_url ) return load_feedback_page( request, url, self, submission, no_penalties=no_penalties )
def get_load_url(self, language, request, students, url_name="exercise"): if self.id: if request.user.is_authenticated: user = request.user submission_count = self.get_submissions_for_student( user.userprofile, exclude_errors=True).count() else: user = None submission_count = 0 # Make grader async URL for the currently authenticated user. # The async handler will handle group selection at submission time. submission_url = update_url_params( api_reverse("exercise-grader", kwargs={'exercise_id': self.id}), get_graderauth_exercise_params(self, user), ) return self._build_service_url(language, request, students, submission_count + 1, url_name, submission_url) return super().get_load_url(language, request, students, url_name)
def get_load_url(self, language, request, students, url_name="exercise"): if self.id: if request.user.is_authenticated(): user = request.user submission_count = self.get_submissions_for_student(user.userprofile).count() else: user = None submission_count = 0 # Make grader async URL for the currently authenticated user. # The async handler will handle group selection at submission time. submission_url = update_url_params( api_reverse("exercise-grader", kwargs={ 'exercise_id': self.id }), get_graderauth_exercise_params(self, user), ) return self._build_service_url( language, request, students, submission_count + 1, url_name, submission_url ) return super().get_load_url(language, request, students, url_name)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['user_profiles'].widget.attrs[ "data-search-api-url"] = api_reverse("user-list")
def __init__(self, *args: Any, **kwargs: Any) -> None: course_instance = kwargs.pop('instance') super(SelectUsersForm, self).__init__(*args, **kwargs) self.fields['user'].widget.search_api_url = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}) self.fields['user'].queryset = course_instance.get_student_profiles()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['teachers'].initial_queryset = self.instance.teachers.all() self.fields['teachers'].widget.attrs[ "data-search-api-url"] = api_reverse("user-list")
def __init__(self, service, user, instance, host, title, context_id=None, link_id=None, add=None): self.service = service course = instance.course # Context and resource parameters. context_id = context_id or (host + instance.get_absolute_url()) link_id = link_id or "aplus{:d}".format(service.pk) title = title or link_id student_id = self.external_student_id(user) # Determine user role. role = "Student" if course.is_teacher(user): role = "Instructor" elif instance.is_assistant(user): role = "TA,TeachingAssistant" self.parameters = add or {} self.parameters.update({ "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": link_id, "resource_link_title": title, # User. "user_id": student_id, "roles": role, "lis_person_name_full": "{} {}".format(user.first_name, user.last_name), "lis_person_name_given": user.first_name, "lis_person_name_family": user.last_name, "lis_person_contact_email_primary": user.email, # Selected course. "context_id": context_id, "context_title": course.name, "context_label": course.code, "launch_presentation_locale": get_language(), "tool_consumer_instance_guid": host + "/aplus", "tool_consumer_instance_name": "A+ LMS", }) if service.enable_api_access: self.parameters.update({ # FIXME: we need request or full host with protocol here! 'custom_context_api': '//' + host + api_reverse("course-detail", kwargs={'course_id': instance.id}), 'custom_context_api_id': str(instance.id), 'custom_user_api_token': user.userprofile.api_token, })
def __init__(self, *args, **kwargs): course_instance = kwargs.pop('instance') super(SelectUsersForm, self).__init__(*args, **kwargs) self.fields['user'].widget.attrs["data-search-api-url"] = api_reverse( "course-students-list", kwargs={'course_id': course_instance.id}) self.fields['user'].queryset = course_instance.get_student_profiles()
def __init__(self, service, user, instance, host, title, context_id=None, link_id=None, add=None): self.service = service course = instance.course # Context and resource parameters. context_id = context_id or (host + instance.get_absolute_url()) link_id = link_id or "aplus{:d}".format(service.pk) title = title or link_id # Gather user information if service.is_anonymous: # Anonymize user information enrollment = Enrollment.objects.filter(course_instance=instance, user_profile=user.userprofile).first() if not enrollment: raise PermissionDenied() # Creates anon name and id for pre-pseudonymisation Enrollments if not (enrollment.anon_name or enrollment.anon_id): # the model's post_save functions take care of the creation enrollment.save() student_id = "a" + enrollment.anon_id # a for anonymous full_name = enrollment.anon_name given_name, sep, family_name = full_name.rpartition(" ") if not given_name: given_name = "Anonymous" email = "anonymous-{}@aplus.invalid".format(enrollment.anon_id) else: student_id = "i" + self.external_student_id(user) # i for internal full_name = "{} {}".format(user.first_name, user.last_name) given_name = user.first_name family_name = user.last_name email = user.email # Determine user role. role = "Student" if course.is_teacher(user): role = "Instructor" elif instance.is_assistant(user): role = "TA,TeachingAssistant" self.parameters = add or {} self.parameters.update({ "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": link_id, "resource_link_title": title, # User. "user_id": student_id, "roles": role, "lis_person_name_full": full_name, "lis_person_name_given": given_name, "lis_person_name_family": family_name, "lis_person_contact_email_primary": email, # Selected course. "context_id": context_id, "context_title": course.name, "context_label": course.code, "launch_presentation_locale": get_language(), "tool_consumer_instance_guid": host + "/aplus", "tool_consumer_instance_name": "A+ LMS", }) if service.api_access: self.parameters.update({ # FIXME: we need request or full host with protocol here! 'custom_context_api': '//' + host + api_reverse("course-detail", kwargs={'course_id': instance.id}), 'custom_context_api_id': str(instance.id), 'custom_user_api_token': user.userprofile.api_token, })
def __init__(self, service, user, instance, request, title, context_id=None, link_id=None, add=None, exercise=None): self.service = service course = instance.course # Context and resource parameters. context_id = context_id or (request.get_host() + instance.get_absolute_url()) link_id = link_id or "aplus{:d}".format(service.pk) title = title or link_id # Gather user information user_id, given_name, family_name, full_name, email = self.user_info(instance, user) # Determine user role. role = "Learner,Student" # Student is not a standard role name, but it has been used here before if course.is_teacher(user): role = "Instructor" elif instance.is_assistant(user): role = "TA,TeachingAssistant" # "TA" is not a standard role self.parameters = add or {} self.parameters.update({ "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": link_id, "resource_link_title": title, # User. "user_id": user_id, "roles": role, "lis_person_name_full": full_name, "lis_person_name_given": given_name, "lis_person_name_family": family_name, "lis_person_contact_email_primary": email, # Selected course. "context_id": context_id, "context_title": course.name, "context_label": course.code, "launch_presentation_locale": get_language(), "launch_presentation_document_target": "iframe" if exercise and exercise.open_in_iframe else "window", "launch_presentation_return_url": request.scheme + '://' + request.get_host() + instance.get_absolute_url(), "tool_consumer_instance_guid": request.get_host() + "/aplus", "tool_consumer_instance_name": "A+ LMS", }) if service.api_access: self.parameters.update({ 'custom_context_api': request.scheme + '://' + request.get_host() + api_reverse("course-detail", kwargs={'course_id': instance.id}), 'custom_context_api_id': str(instance.id), 'custom_user_api_token': user.userprofile.api_token, }) if exercise: # LTI 1.1 Tool Provider may return grades to A+ (Tool Consumer) self.parameters.update({ # Outcome Service requests from the LTI Tool Provider include the # sourcedid from the launch request. It is used to create new submissions # for storing the points of the user. "lis_result_sourcedid": "{}-{}".format(exercise.pk, user_id), # The LTI Tool Provider posts Outcome Service requests to this URL (i.e., points for a submission) "lis_outcome_service_url": reverse('lti-outcomes', request=request, kwargs={'version': api_settings.DEFAULT_VERSION}), })
def __init__(self, service, user, instance, request, title, context_id=None, link_id=None, add=None, exercise=None): self.service = service course = instance.course base_url_parts = urlsplit(settings.BASE_URL) # Context and resource parameters. context_id = context_id or (base_url_parts.netloc + instance.get_absolute_url()) link_id = link_id or "aplus{:d}".format(service.pk) title = title or link_id # Gather user information user_id, given_name, family_name, full_name, email = self.user_info(instance, user) # Determine user role. role = "Learner,Student" # Student is not a standard role name, but it has been used here before if course.is_teacher(user): role = "Instructor" elif instance.is_assistant(user): role = "TA,TeachingAssistant" # "TA" is not a standard role self.parameters = add or {} self.parameters.update({ "lti_version": "LTI-1p0", "lti_message_type": "basic-lti-launch-request", "resource_link_id": link_id, "resource_link_title": title, # User. "user_id": user_id, "roles": role, "lis_person_name_full": full_name, "lis_person_name_given": given_name, "lis_person_name_family": family_name, "lis_person_contact_email_primary": email, # Selected course. "context_id": context_id, "context_title": course.name, "context_label": course.code, "launch_presentation_locale": get_language(), "launch_presentation_document_target": "iframe" if exercise and exercise.open_in_iframe else "window", "launch_presentation_return_url": urljoin(settings.BASE_URL, instance.get_absolute_url()), "tool_consumer_instance_guid": base_url_parts.netloc + "/aplus", "tool_consumer_instance_name": settings.BRAND_NAME, "tool_consumer_instance_description": settings.BRAND_DESCRIPTION, "tool_consumer_instance_url": settings.BASE_URL, }) if service.api_access: self.parameters.update({ 'custom_context_api': settings.BASE_URL + api_reverse("course-detail", kwargs={'course_id': instance.id}), 'custom_context_api_id': str(instance.id), 'custom_user_api_token': user.userprofile.api_token, }) if exercise: # LTI 1.1 Tool Provider may return grades to A+ (Tool Consumer) self.parameters.update({ # Outcome Service requests from the LTI Tool Provider include the # sourcedid from the launch request. It is used to create new submissions # for storing the points of the user. "lis_result_sourcedid": "{}-{}".format(exercise.pk, user_id), # The LTI Tool Provider posts Outcome Service requests to this URL (i.e., points for a submission) "lis_outcome_service_url": reverse('lti-outcomes', request=request, kwargs={'version': api_settings.DEFAULT_VERSION}), })