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

Это пятое прохождение в серии прохождений дополнений Класса.

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

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

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

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

  • Измените предыдущие запросы на создание вложений к API Класса, чтобы создать вложение типа действия.
  • Внедрите постоянное хранилище для материалов учащихся.
  • Измените предыдущий маршрут просмотра учащихся, чтобы принимать входные данные учащихся.
  • Укажите маршрут для обслуживания iframe обзора работ учащихся.

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

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

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

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

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

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

Питон

В нашем примере это метод 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 : уникальный идентификатор вложения. Назначается Классом и возвращается в ответе при создании вложения.
  • submission_id : идентификатор заявки учащегося. Назначается Классом и возвращается в ответе getAddOnContext в представлении учащихся.
  • student_response : ответ, предоставленный студентом.

Питон

Расширьте реализацию 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 .

Питон

В нашем примере это метод 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 , которое указывает такие состояния, как, например, открыл ли учащийся вложение или сдал его. Это может быть полезно, если вы хотите запретить внесение изменений в сданную отправку или если вы заинтересованы в предоставлении преподавателю понимание прогресса своих учеников:

Питон

В нашем примере это продолжение метода 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()

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

Питон

В нашем примере это продолжение метода 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 при создании вложения. Этот маршрут открывается, когда учитель просматривает работу учащегося в пользовательском интерфейсе оценщика Класса.

Вы получаете параметр запроса submissionId , когда Класс открывает iframe обзора работ учащихся. Используйте его, чтобы получить работу учащегося из вашей локальной базы данных:

Питон

В нашем примере это находится в файле 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 после завершения действия. При желании нажмите кнопку «Сдать» .

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

  • Войдите в Класс как пользователь- тестировщик .
  • Найдите столбец вашего тестового задания на вкладке «Оценки» . Нажмите на название вашего тестового задания.
  • Найдите карточку пользователя-испытателя. Нажмите на вложение на карточке.

Убедитесь, что учащемуся отображается правильное задание.

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