Вложения типа деятельности

Это пятое пошаговое руководство из серии руководств по использованию дополнений для класса.

В этом пошаговом руководстве вы модифицируете пример из предыдущего шага, чтобы создать вложение типа «задание». Это любые вложения, требующие от студента提交, такие как письменный ответ, тест или другой созданный студентом материал.

Важно различать вложения типа «контент» и вложения типа «деятельность». Вложения типа «деятельность» отличаются от вложений типа «контент» следующим образом:

  • В правом верхнем углу окна просмотра для студентов (iframe) появляется кнопка «Сдать работу».
  • Они служат уникальным идентификатором для студенческих работ.
  • Карточка с прикрепленным файлом отображается в пользовательском интерфейсе оценочной системы Classroom.
  • Они могут выставлять оценки за задание, к которому относятся.

Обсуждение системы оценивания смотрите в следующем пошаговом руководстве. В ходе этого руководства вы выполните следующие действия:

  • Измените предыдущие запросы на создание вложений к API Classroom, чтобы создавать вложения типа "Задание".
  • Внедрить постоянное хранилище для студенческих работ.
  • Измените предыдущий интерфейс «Просмотр студента», чтобы он принимал ввод данных от студентов.
  • Предоставьте маршрут для отображения iframe с обзором студенческих работ.

После завершения работы вы можете создавать вложения в виде заданий через пользовательский интерфейс Google Classroom, войдя в систему как учитель. Ученики класса также могут выполнить задание во фрейме и отправить ответ. Учитель может просмотреть работу ученика в интерфейсе оценивания Classroom.

Для целей этого примера повторно используйте шаблон вложения из предыдущего пошагового руководства, который содержит изображение известной достопримечательности и подпись с ее названием. Задание состоит в том, чтобы предложить ученику указать название достопримечательности.

Измените запрос на создание вложения.

Перейдите к тому разделу кода, в котором вы создали вложение типа контента в предыдущем пошаговом руководстве. Ключевым элементом здесь является экземпляр объекта AddOnAttachment , в котором мы ранее указали teacherViewUri , studentViewUri и title для вложения.

Хотя для всех дополнительных файлов требуются эти три поля, наличие или отсутствие studentWorkReviewUri определяет, является ли файл файлом типа «деятельность» или «контент». Запрос CREATE с заполненным полем studentWorkReviewUri становится файлом типа «деятельность», а запрос CREATE без поля studentWorkReviewUri — файлом типа «контент».

Единственное изменение, которое нужно внести в этот запрос, — это заполнить поле studentWorkReviewUri . Добавьте здесь маршрут с соответствующим именем; вы реализуете его на более позднем этапе.

Python

В приведенном нами примере это находится в методе create_attachments в файле webapp/attachment_routes.py .

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    # The presence of this field marks this as an activity-type attachment.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

Добавьте постоянное хранилище для вложений типа контента.

Запишите ответ ученика на наше задание. Вы сможете найти его позже, когда учитель увидит работу ученика в iframe «Обзор работы ученика».

Создайте схему базы данных для Submission . В приведенном примере предполагается, что студенты введут название достопримечательности, изображенной на картинке. Таким образом, Submission содержит следующие атрибуты:

  • attachment_id : Уникальный идентификатор для вложения. Присваивается Classroom и возвращается в ответе при создании вложения.
  • submission_id : Идентификатор работы студента. Присваивается Classroom и возвращается в ответе getAddOnContext в представлении студента.
  • student_response : Ответ, предоставленный студентом.

Python

Расширьте реализацию SQLite и flask_sqlalchemy , описанную в предыдущих шагах.

Перейдите к файлу, в котором вы определили предыдущие таблицы ( models.py если вы следуете нашему примеру). Добавьте следующий код в конец файла.

# Database model to represent a student submission.
class Submission(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    submission_id = db.Column(db.String(120), primary_key=True)

    # The unique identifier for the student's submission.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The student's response to the question prompt.
    student_response = db.Column(db.String(120))

Импортируйте новый класс Submission в файл сервера вместе с маршрутами обработки вложений.

Измените маршрут "Просмотр студента".

Далее измените предыдущий маршрут представления студента, чтобы отобразить небольшую форму и принять ввод от студента. Вы можете повторно использовать большую часть кода из предыдущего пошагового руководства.

Найдите код сервера, который предоставляет маршрут для вашего представления студента. Это маршрут, указанный в поле studentViewUri при создании вложения. Первое изменение, которое необходимо внести, — это извлечь submissionId из ответа getAddOnContext .

Python

В приведенном нами примере это находится в методе load_activity_attachment в файле webapp/attachment_routes.py .

# Issue a request to the courseWork.getAddOnContext endpoint
addon_context_response = classroom_service.courses().courseWork(
).getAddOnContext(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"]).execute()

# One of studentContext or teacherContext will be populated.
user_context = "student" if addon_context_response.get(
    "studentContext") else "teacher"

# If the user is a student...
if user_context == "student":
    # Extract the submissionId from the studentContext object.
    # This value is provided by Google Classroom.
    flask.session["submissionId"] = addon_context_response.get(
            "studentContext").get("submissionId")

Вы также можете отправить запрос на получение статуса отправки работы студентом . Ответ содержит значение SubmissionState , которое указывает на такие состояния, как то, открыл ли студент вложенную работу или отправил её. Это может быть полезно, если вы хотите запретить редактирование отправленной работы или если вас интересует предоставление преподавателю информации об успеваемости его учеников.

Python

В приведенном нами примере это продолжение метода load_activity_attachment , описанного выше.

# Issue a request to get the status of the student submission.
submission_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().get(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"]).execute()

Наконец, получите информацию о вложении из нашей базы данных и отобразите форму ввода. Форма в приведенном примере состоит из поля ввода строки и кнопки отправки. Покажите изображение достопримечательности и предложите студенту ввести ее название. После того, как он даст ответ, запишите его в нашу базу данных.

Python

В приведенном нами примере это продолжение метода load_activity_attachment , описанного выше.

# Look up the attachment in the database.
attachment = Attachment.query.get(flask.session["attachmentId"])

message_str = f"I see that you're a {user_context}! "
message_str += (
    f"I've loaded the attachment with ID {attachment.attachment_id}. "
    if user_context == "teacher" else
    "Please complete the activity below.")

form = activity_form_builder()

if form.validate_on_submit():
    # Record the student's response in our database.

    # Check if the student has already submitted a response.
    # If so, update the response stored in the database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    if student_submission is not None:
        student_submission.student_response = form.student_response.data
    else:
        # Store the student's response by the submission ID.
        new_submission = Submission(
            submission_id=flask.session["submissionId"],
            attachment_id=flask.session["attachmentId"],
            student_response=form.student_response.data)
        db.session.add(new_submission)

    db.session.commit()

    return flask.render_template(
        "acknowledge-submission.html",
        message="Your response has been recorded. You can close the " \
            "iframe now.",
        instructions="Please Turn In your assignment if you have " \
            "completed all tasks."
    )

# Show the activity.
return flask.render_template(
    "show-activity-attachment.html",
    message=message_str,
    image_filename=attachment.image_filename,
    image_caption=attachment.image_caption,
    user_context=user_context,
    form=form,
    responses=response_strings)

Для обеспечения различий между пользователями рекомендуется отключить функцию отправки и вместо этого отображать правильный ответ в режиме просмотра для учителя.

Добавьте маршрут для iframe «Обзор студенческих работ».

Наконец, добавьте маршрут для отображения iframe с обзором студенческой работы. Имя этого маршрута должно совпадать с именем, указанным для studentWorkReviewUri при создании вложения. Этот маршрут открывается, когда преподаватель просматривает работу студента в пользовательском интерфейсе оценщика Classroom.

Параметр запроса submissionId отображается при открытии iframe «Проверка студенческих работ» в Classroom. Используйте его для получения работы студента из вашей локальной базы данных:

Python

В приведенном нами примере это находится в файле webapp/attachment_routes.py .

@app.route("/view-submission")
def view_submission():
    """
    Render a student submission using the show-student-submission.html template.
    """

    # Save the query parameters passed to the iframe in the session, just as we did
    # in previous routes. Abbreviated here for readability.
    add_iframe_query_parameters_to_session(flask.request.args)

    # For the sake of brevity in this example, we'll skip the conditional logic
    # to see if we need to authorize the user as we have done in previous steps.
    # We can assume that the user that reaches this route is a teacher that has
    # already authorized and created an attachment using the add-on.

    # In production, we recommend fully validating the user's authorization at
    # this stage as well.

    # Look up the student's submission in our database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    # Look up the attachment in the database.
    attachment = Attachment.query.get(student_submission.attachment_id)

    # Render the student's response alongside the correct answer.
    return flask.render_template(
        "show-student-submission.html",
        message=f"Loaded submission {student_submission.submission_id} for "\
            f"attachment {attachment.attachment_id}.",
        student_response=student_submission.student_response,
        correct_answer=attachment.image_caption)

Протестируйте дополнение

Повторите шаги по тестированию дополнения из предыдущего пошагового руководства . У вас должен получиться файл, который студент сможет открыть.

Выполните следующие шаги, чтобы проверить привязку действия:

  • Войдите в Google Classroom как один из тестируемых учеников в том же классе, что и тестируемый учитель.
  • Перейдите на вкладку «Задания» и разверните раздел «Тестовое задание» .
  • Нажмите на карточку прикрепленного дополнения , чтобы открыть представление для учащихся и отправить ответ на задание.
  • Закройте iframe после завершения задания. При желании нажмите кнопку «Сдать» .

После завершения задания в Classroom ничего не должно измениться. Теперь протестируйте iframe «Обзор студенческой работы»:

  • Войдите в Classroom как пользователь, проводящий тестирование в качестве учителя .
  • Найдите столбец с вашим тестовым заданием на вкладке «Оценки» . Щелкните по названию вашего тестового задания.
  • Найдите карточку пользователя, проходящего тестирование. Щелкните по прикрепленному файлу на карточке.

Убедитесь, что для студента отображается корректная версия работы.

Поздравляем! Вы готовы перейти к следующему шагу: синхронизации оценок вложений .