活動類型附件

這是 Classroom 外掛程式逐步操作說明系列中的第五逐步操作說明。

在本逐步操作說明中,您將修改上一個逐步操作說明中的範例,以產生活動類型附件。這些是需要學生繳交的附件,例如書面回覆、測驗或其他學生產生的成果。

內容類型和活動類型附件之間的差異非常重要。活動類型附件與內容類型附件的差異如下:

  • 學生檢視畫面 iframe 的右上方會顯示「繳交」按鈕。
  • 提供了學生作業的專屬 ID。
  • 他們的附件資訊卡會顯示在 Classroom 評分工具 UI 中。
  • 他們可以為屬於自己的作業設定成績。

如需評分的相關討論,請參閱下一篇逐步操作說明。在本逐步操作說明中,您將完成下列步驟:

  • 修改先前對 Classroom API 的連結建立要求,以建立活動類型的附件。
  • 實作永久儲存空間來儲存學生繳交的作業。
  • 修改先前的學生檢視畫面路徑,以接受學生輸入內容。
  • 提供「學生作業回顧」iframe 的路徑。

完成之後,請以老師身分登入,透過 Google Classroom UI 在作業中建立活動類型的附件。課堂學生也可以完成 iframe 中的活動並提交回應。老師可在 Classroom 評分 UI 中查看學生繳交的作業。

為了方便起見,請重複使用上一個逐步操作說明中的附件範本,其中顯示知名地標的圖片和地標名稱說明文字。此活動包含提示學生提供地標名稱。

修改附件建立要求

前往您在上一個逐步操作說明中建立內容類型附件的程式碼區段。這裡的鍵項目是 AddOnAttachment 物件的執行個體,我們先前為連結指定 teacherViewUristudentViewUrititle

所有外掛程式附件都需要這三個欄位,而是否存在 studentWorkReviewUri 會決定連結屬於活動類型還是內容類型。含有已填入 studentWorkReviewUriCREATE 要求會成為活動類型的附件,而沒有 studentWorkReviewUriCREATE 要求則會變為內容類型附件。

這項要求的唯一修改方式是填入 studentWorkReviewUri 欄位。請在這裡新增命名正確的路徑;您將在後續步驟中實作這個路徑。

Python

在我們提供的範例中,這位於 webapp/attachment_routes.py 檔案的 create_attachments 方法中。

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:附件的專屬 ID。會由 Classroom 指派,並在建立連結時在回應中傳回。
  • submission_id:學生繳交作業的 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 欄位中指定的路徑。第一個變更是從 getAddOnContext 回應中擷取 submissionId

Python

在我們提供的範例中,這位於 webapp/attachment_routes.py 檔案的 load_activity_attachment 方法中。

# 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 評分工具 UI 中查看學生提交的內容時,就會開啟這個路徑。

當 Classroom 開啟學生工作審查 iframe 時,您會收到 submissionId 查詢參數。請使用此方法從本機資料庫中擷取學生的作業:

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。或者,按一下 [Turn In] (繳交) 按鈕。

完成活動後,您在 Classroom 中應該就不會看到任何變更。現在請測試學生作業回顧 iframe:

  • 以「老師」的測試使用者身分登入 Classroom。
  • 在「成績」分頁中找出測試作業的資料欄。按一下測試作業的名稱。
  • 找出測試學生使用者的資訊卡。按一下資訊卡上的附件。

確認學生提交的作業正確無誤。

恭喜!您可以開始進行下一個步驟:同步處理附件成績