Пример #1
0
    def post(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)

        if not assignment.answer_grace and not allow(MANAGE, assignment):
            abort(
                403,
                title="Answer Not Submitted",
                message=
                "Sorry, the answer deadline has passed. No answers can be submitted after the deadline unless the instructor submits the answer for you."
            )

        require(
            CREATE,
            Answer(course_id=course.id),
            title="Answer Not Submitted",
            message=
            "Answers can be submitted only by those enrolled in the course. Please double-check your enrollment in this course."
        )
        restrict_user = not allow(MANAGE, assignment)

        answer = Answer(assignment_id=assignment.id)

        params = new_answer_parser.parse_args()
        answer.content = params.get("content")
        answer.draft = params.get("draft")

        file_uuid = params.get('file_id')
        attachment = None
        if file_uuid:
            attachment = File.get_by_uuid_or_404(file_uuid)
            answer.file_id = attachment.id
        else:
            answer.file_id = None

        # non-drafts must have content
        if not answer.draft and not answer.content and not file_uuid:
            abort(
                400,
                title="Answer Not Submitted",
                message=
                "Please provide content in the text editor or upload a file and try submitting again."
            )

        user_uuid = params.get("user_id")
        group_uuid = params.get("group_id")
        # we allow instructor and TA to submit multiple answers for other users in the class
        if user_uuid and not allow(MANAGE, Answer(course_id=course.id)):
            abort(
                400,
                title="Answer Not Submitted",
                message=
                "Only instructors and teaching assistants can submit an answer on behalf of another."
            )
        if group_uuid and not assignment.enable_group_answers:
            abort(400,
                  title="Answer Not Submitted",
                  message="Group answers are not allowed for this assignment.")
        if group_uuid and not allow(MANAGE, Answer(course_id=course.id)):
            abort(
                400,
                title="Answer Not Submitted",
                message=
                "Only instructors and teaching assistants can submit an answer on behalf of a group."
            )
        if group_uuid and user_uuid:
            abort(
                400,
                title="Answer Not Submitted",
                message=
                "You cannot submit an answer for a user and a group at the same time."
            )

        user = User.get_by_uuid_or_404(
            user_uuid) if user_uuid else current_user
        group = Group.get_active_by_uuid_or_404(
            group_uuid) if group_uuid else None

        if restrict_user and assignment.enable_group_answers and not group:
            group = current_user.get_course_group(course.id)
            if group == None:
                abort(
                    400,
                    title="Answer Not Submitted",
                    message=
                    "You are currently not in any group for this course. Please contact your instructor to be added to a group."
                )

        check_for_existing_answers = False
        if group and assignment.enable_group_answers:
            if group.course_id != course.id:
                abort(
                    400,
                    title="Answer Not Submitted",
                    message=
                    "Group answers can be submitted to courses they belong in."
                )

            answer.user_id = None
            answer.group_id = group.id
            answer.comparable = True
            check_for_existing_answers = True
        else:
            answer.user_id = user.id
            answer.group_id = None

            course_role = User.get_user_course_role(answer.user_id, course.id)

            # only system admin can add answers for themselves to a class without being enrolled in it
            # required for managing comparison examples as system admin
            if (not course_role or course_role == CourseRole.dropped
                ) and current_user.system_role != SystemRole.sys_admin:
                abort(
                    400,
                    title="Answer Not Submitted",
                    message=
                    "Answers can be submitted only by those enrolled in the course. Please double-check your enrollment in this course."
                )

            if course_role == CourseRole.student and assignment.enable_group_answers:
                abort(
                    400,
                    title="Answer Not Submitted",
                    message=
                    "Students can only submit group answers for this assignment."
                )

            # we allow instructor and TA to submit multiple answers for their own,
            # but not for student. Each student can only have one answer.
            if course_role and course_role == CourseRole.student:
                check_for_existing_answers = True
                answer.comparable = True
            else:
                # instructor / TA / Sys Admin can mark the answer as non-comparable, unless the answer is for a student
                answer.comparable = params.get("comparable")

        if check_for_existing_answers:
            # check for answers with user_id or group_id
            prev_answers = Answer.query \
                .filter_by(
                    assignment_id=assignment.id,
                    user_id=answer.user_id,
                    group_id=answer.group_id,
                    active=True
                ) \
                .all()

            # check if there is a previous answer submitted for the student
            non_draft_answers = [
                prev_answer for prev_answer in prev_answers
                if not prev_answer.draft
            ]
            if len(non_draft_answers) > 0:
                abort(
                    400,
                    title="Answer Not Submitted",
                    message=
                    "An answer has already been submitted for this assignment by you or on your behalf."
                )

            # check if there is a previous draft answer submitted for the student (soft-delete if present)
            draft_answers = [
                prev_answer for prev_answer in prev_answers
                if prev_answer.draft
            ]
            for draft_answer in draft_answers:
                draft_answer.active = False

        # set submission date if answer is being submitted for the first time
        if not answer.draft and not answer.submission_date:
            answer.submission_date = datetime.datetime.utcnow()

        answer.update_attempt(params.get('attempt_uuid'),
                              params.get('attempt_started', None),
                              params.get('attempt_ended', None))

        db.session.add(answer)
        db.session.commit()

        on_answer_create.send(self,
                              event_name=on_answer_create.name,
                              user=current_user,
                              course_id=course.id,
                              answer=answer,
                              data=marshal(
                                  answer,
                                  dataformat.get_answer(restrict_user)))

        if attachment:
            on_attach_file.send(self,
                                event_name=on_attach_file.name,
                                user=current_user,
                                course_id=course.id,
                                file=attachment,
                                data={
                                    'answer_id': answer.id,
                                    'file_id': attachment.id
                                })

        # update course & assignment grade for user if answer is fully submitted
        if not answer.draft:
            if answer.user:
                assignment.calculate_grade(answer.user)
                course.calculate_grade(answer.user)
            elif answer.group:
                assignment.calculate_group_grade(answer.group)
                course.calculate_group_grade(answer.group)

        return marshal(answer, dataformat.get_answer(restrict_user))
Пример #2
0
    def post(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)

        if not assignment.answer_grace and not allow(MANAGE, assignment):
            abort(403, title="Answer Not Submitted", message="Sorry, the answer deadline has passed. No answers can be submitted after the deadline unless the instructor submits the answer for you.")

        require(CREATE, Answer(course_id=course.id),
            title="Answer Not Submitted",
            message="Answers can be submitted only by those enrolled in the course. Please double-check your enrollment in this course.")
        restrict_user = not allow(MANAGE, assignment)

        answer = Answer(assignment_id=assignment.id)

        params = new_answer_parser.parse_args()
        answer.content = params.get("content")
        answer.draft = params.get("draft")

        file_uuid = params.get('file_id')
        attachment = None
        if file_uuid:
            attachment = File.get_by_uuid_or_404(file_uuid)
            answer.file_id = attachment.id
        else:
            answer.file_id = None

        # non-drafts must have content
        if not answer.draft and not answer.content and not file_uuid:
            abort(400, title="Answer Not Submitted", message="Please provide content in the text editor or upload a file and try submitting again.")

        user_uuid = params.get("user_id")
        group_uuid = params.get("group_id")
        # we allow instructor and TA to submit multiple answers for other users in the class
        if user_uuid and not allow(MANAGE, Answer(course_id=course.id)):
            abort(400, title="Answer Not Submitted", message="Only instructors and teaching assistants can submit an answer on behalf of another.")
        if group_uuid and not assignment.enable_group_answers:
            abort(400, title="Answer Not Submitted", message="Group answers are not allowed for this assignment.")
        if group_uuid and not allow(MANAGE, Answer(course_id=course.id)):
            abort(400, title="Answer Not Submitted", message="Only instructors and teaching assistants can submit an answer on behalf of a group.")
        if group_uuid and user_uuid:
            abort(400, title="Answer Not Submitted", message="You cannot submit an answer for a user and a group at the same time.")

        user = User.get_by_uuid_or_404(user_uuid) if user_uuid else current_user
        group = Group.get_active_by_uuid_or_404(group_uuid) if group_uuid else None

        if restrict_user and assignment.enable_group_answers and not group:
            group = current_user.get_course_group(course.id)
            if group == None:
                abort(400, title="Answer Not Submitted",
                    message="You are currently not in any group for this course. Please contact your instructor to be added to a group.")

        check_for_existing_answers = False
        if group and assignment.enable_group_answers:
            if group.course_id != course.id:
                abort(400, title="Answer Not Submitted",
                    message="Group answers can be submitted to courses they belong in.")

            answer.user_id = None
            answer.group_id = group.id
            answer.comparable = True
            check_for_existing_answers = True
        else:
            answer.user_id = user.id
            answer.group_id = None

            course_role = User.get_user_course_role(answer.user_id, course.id)

            # only system admin can add answers for themselves to a class without being enrolled in it
            # required for managing comparison examples as system admin
            if (not course_role or course_role == CourseRole.dropped) and current_user.system_role != SystemRole.sys_admin:
                abort(400, title="Answer Not Submitted", message="Answers can be submitted only by those enrolled in the course. Please double-check your enrollment in this course.")

            if course_role == CourseRole.student and assignment.enable_group_answers:
                abort(400, title="Answer Not Submitted", message="Students can only submit group answers for this assignment.")

            # we allow instructor and TA to submit multiple answers for their own,
            # but not for student. Each student can only have one answer.
            if course_role and course_role == CourseRole.student:
                check_for_existing_answers = True
                answer.comparable = True
            else:
                # instructor / TA / Sys Admin can mark the answer as non-comparable, unless the answer is for a student
                answer.comparable = params.get("comparable")

        if check_for_existing_answers:
            # check for answers with user_id or group_id
            prev_answers = Answer.query \
                .filter_by(
                    assignment_id=assignment.id,
                    user_id=answer.user_id,
                    group_id=answer.group_id,
                    active=True
                ) \
                .all()

            # check if there is a previous answer submitted for the student
            non_draft_answers = [prev_answer for prev_answer in prev_answers if not prev_answer.draft]
            if len(non_draft_answers) > 0:
                abort(400, title="Answer Not Submitted", message="An answer has already been submitted for this assignment by you or on your behalf.")

            # check if there is a previous draft answer submitted for the student (soft-delete if present)
            draft_answers = [prev_answer for prev_answer in prev_answers if prev_answer.draft]
            for draft_answer in draft_answers:
                draft_answer.active = False

        # set submission date if answer is being submitted for the first time
        if not answer.draft and not answer.submission_date:
            answer.submission_date = datetime.datetime.utcnow()

        answer.update_attempt(
            params.get('attempt_uuid'),
            params.get('attempt_started', None),
            params.get('attempt_ended', None)
        )

        db.session.add(answer)
        db.session.commit()

        on_answer_create.send(
            self,
            event_name=on_answer_create.name,
            user=current_user,
            course_id=course.id,
            answer=answer,
            data=marshal(answer, dataformat.get_answer(restrict_user)))

        if attachment:
            on_attach_file.send(
                self,
                event_name=on_attach_file.name,
                user=current_user,
                course_id=course.id,
                file=attachment,
                data={'answer_id': answer.id, 'file_id': attachment.id})

        # update course & assignment grade for user if answer is fully submitted
        if not answer.draft:
            if answer.user:
                assignment.calculate_grade(answer.user)
                course.calculate_grade(answer.user)
            elif answer.group:
                assignment.calculate_group_grade(answer.group)
                course.calculate_group_grade(answer.group)

        return marshal(answer, dataformat.get_answer(restrict_user))