外部附件與回報;繳交

這是 Classroom 外掛程式操作說明系列的第七集操作說明。

在本逐步操作說明中,您將在網頁應用程式中新增行為,從 Google Classroom 以外的地方建立外掛程式附件。使用這項行為,讓使用者從現有產品或網站建立外掛程式附件。這也是 CourseWork 整合的絕佳附加功能,因為您可以將現有流量導向外掛程式提供的改善版使用者體驗,而無須變更流程。如需建議的程序,請參閱「在 Classroom 外建立附件」指南頁面。

您也可以在外掛程式中新增行為,以程式輔助方式修改附有外掛程式附件的作業。無論作業是由誰建立,只要作業含有您的外掛程式附件,您都可以修改該作業。這項功能對於學生完成活動後繳交作業特別實用,可向老師傳達學生已完成指定作業,並準備好讓老師審查。

您可以擴充支援內容類型活動類型附件的最終版本外掛程式。本指南使用內容類型附件。

新增作業管理 OAuth 範圍

請確認應用程式要求下列權限範圍:

  • https://www.googleapis.com/auth/classroom.addons.teacher
  • https://www.googleapis.com/auth/classroom.addons.student
  • https://www.googleapis.com/auth/classroom.coursework.students

classroom.coursework.students 範圍先前並未使用,而是用於建立或修改 CourseWork 指派。將這個範圍新增至 Cloud 專案 Google Workspace Marketplace SDKOAuth 同意畫面和伺服器程式碼中的範圍清單。

Python

  SCOPES = [
    "https://www.googleapis.com/auth/classroom.addons.teacher",
    "https://www.googleapis.com/auth/classroom.addons.student",
    "https://www.googleapis.com/auth/classroom.coursework.students",
  ]

在 Classroom 中建立作業

在非 iframe 網頁中新增按鈕

這份逐步操作說明中所述的流程可讓使用者透過非 Google 產品建立 Google Classroom 作業和附件。實際上,這可能是您現有的網站或應用程式。在本例中,您需要建立模擬網頁,用來充當外部網站。您需要一個按鈕或連結,當使用者點選時,會開啟新的路徑,執行建議的 CourseWork 流程來建立新的作業。

如果您尚未新增按鈕或連結,也需要新增按鈕或連結,讓使用者登入。您需要使用者憑證才能提出後續 API 要求,因此必須完成 OAuth 2.0 握手程序。如需具體指引,請參閱登入操作說明

Python

提供的 Python 範例會修改第一個逐步操作步驟中介紹的 /index 路徑。

<!-- /webapp/templates/index.html -->
<a href="clear-credentials.html">Logout</a>
<a href="start-auth-flow.html">Login</a>

<br>

<a href="create-coursework-assignment.html">Create a CourseWork Assignment</a>

新增 HTML 範本,代表網站中的目的地。這個頁面會代表要附加至 CourseWork 作業的內容。

<!-- /webapp/templates/example-coursework-assignment.html -->
<h1>CourseWork assignment loaded!</h1>
<p>You've loaded a CourseWork assignment! It was created from an external web page.</p>

建立新的 Python 模組檔案,以便處理 CourseWork 相關路徑。這是我們提供範例中的 coursework_routes.py。新增下列三個路線,請注意,您稍後會填入部分內容。

# /webapp/coursework_routes.py
@app.route("/create-coursework-assignment")
def create_coursework_assignment():
  """
  Completes the assignment creation flow.
  """

  # Check that the user is signed in. If not, perform the OAuth 2.0
  # authorization flow.
  credentials = get_credentials()

  if not credentials:
    return start_auth_flow("coursework_assignment_callback")

  # Construct the Google Classroom service.
  classroom_service = get_classroom_service()

  pass  # To be completed later.

@app.route("/example-coursework-assignment/<assignment_type>")
def example_coursework_assignment(assignment_type):
  """
  Renders the "example-coursework-assignment.html" template.
  """
  return flask.render_template(
      "example-coursework-assignment.html", assignment_type=assignment_type
  )

@app.route("/coursework-assignment-callback")
def coursework_assignment_callback():
  """
  Completes the OAuth 2.0 handshake and stores credentials in the session.
  This is identical to the callback introduced in the sign-in walkthrough,
  but redirects the user to the index page instead of the attachment
  discovery page.
  """
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE,
      scopes=SCOPES,
      state=flask.session["state"],
      redirect_uri=flask.url_for("coursework_assignment_callback", _external=True),
  )

  flow.fetch_token(authorization_response=flask.request.url)

  credentials = flow.credentials
  flask.session["credentials"] = session_credentials_to_dict(
      credentials
  )

  # Close the current window and redirect the user to the index page.
  return flask.render_template("close-me.html", redirect_destination="index")

檢查使用者是否符合建立附件的資格

使用者必須符合多項必要條件,您才能代為建立外掛程式附件。為方便使用者,Google 提供 userProfiles.checkUserCapability 方法,用於判斷使用者是否符合這些先決條件。符合先決條件的使用者稱為符合資格的使用者。

CourseWork 建立路徑實作中加入資格檢查。接著測試回應中的 allowed 欄位。對於符合資格的使用者,請按照邏輯建立附加檔案附件的作業。否則請建立連結素材資源。您必須知道使用者要建立作業的課程 ID。通常您會提示使用者指定要使用的課程。為求簡單起見,我們在本例中使用硬式編碼值。

Python

# /webapp/coursework_routes.py
@app.route("/create-coursework-assignment")
def create_coursework_assignment():
  """
  Completes the assignment creation flow.
  """
  # ... Check that the user is signed in and get the Classroom service ...

  # Check whether the user can create add-on attachments.
  eligibility_response = (
      classroom_service.userProfiles()
      .checkUserCapability(
        userId="me",
        capability="CREATE_ADD_ON_ATTACHMENT",
        # The previewVersion is necessary while the method is available in the
        # Workspace Developer Preview Program.
        previewVersion="V1_20240930_PREVIEW",
      ).execute()
  )
  is_create_attachment_eligible = eligibility_response.get("allowed")

  if is_create_attachment_eligible:
    # See the "Create an assignment with add-on attachment for eligible users" section for implementation.
  if not is_create_attachment_eligible:
    # See the "Create a Link Material" section for implementation.

為符合資格的使用者建立附加檔案作業

如果使用者符合建立外掛程式附件的資格,請按照下列步驟操作:

  1. 傳送 API 要求,在 Google Classroom 中建立不含附件courseWork 作業。
  2. 擷取新建立指派作業的 id
  3. 建立新的 CourseWork AddOnAttachment
  4. 在 Google Classroom 中,針對新建立的作業提出建立外掛程式附件的請求。

Python

# The ID of the course to which the assignment will be added.
course_id = 1234567890  # TODO(developer) Replace with an actual course ID.

# /webapp/coursework_routes.py
if is_create_attachment_eligible:
  # Create an assignment.
  coursework = {
      "title": "My CourseWork Assignment with Add-on Attachment",
      "description": "Created using the Classroom CourseWork API.",
      "workType": "ASSIGNMENT",
      "state": "DRAFT",  # Set to 'PUBLISHED' to assign to students.
  }

  # Issue a request to create the assignment.
  create_assignment_response = (
      classroom_service.courses()
      .courseWork()
      .create(courseId=course_id, body=coursework)
      .execute()
  )

  # Create an add-on attachment that links to the selected content and
  # associate it with the new assignment.
  content_url = flask.url_for(
      "example_coursework_assignment",
      assignment_type="add-on-attachment",
      _scheme="https",
      _external=True,
  )

  # Construct an AddOnAttachment instance.
  attachment = {
      "teacherViewUri": {"uri": content_url},
      "studentViewUri": {"uri": content_url},
      "title": f'Test Attachment for Assignment {create_assignment_response.get("id")}',
  }

  # Issue a request to create the attachment.
  add_on_attachment_response = (
      classroom_service.courses()
      .courseWork()
      .addOnAttachments()
      .create(
          courseId=course_id,
          itemId=create_assignment_response.get("id"),  # ID of the new assignment.
          body=attachment,
      )
      .execute()
  )

如果使用者不符合建立外掛程式附件的資格,請改為建立連結素材,方法如下:

Python

# The ID of the course to which the assignment will be added.
course_id = 1234567890  # TODO(developer) Replace with an actual course ID.

if not is_create_attachment_eligible:
    coursework = {
        "title": "My CourseWork Assignment with Link Material",
        "description": "Created using the Classroom CourseWork API.",
        "workType": "ASSIGNMENT",
        "state": "DRAFT",  # Set to 'PUBLISHED' to assign to students.
        # Specify the URL for your content as a Link Material.
        "materials": [
            {
                "link": {
                    "url": flask.url_for(
                        "example_coursework_assignment",
                        assignment_type="link-material",
                        _scheme="https",
                        _external=True,
                    )
                }
            }
        ],
    }

    # Issue a request to create the assignment.
    assignment_response = (
        classroom_service.courses()
        .courseWork()
        .create(courseId=course_id, body=coursework)
        .execute()
    )

修改已建立的作業

無論是誰建立的串流項目,只要含有至少一個附加檔案,您都可以存取、修改、提交、取回或歸還該項目。訊息串項目是指任何 AnnouncementCourseWork 作業或 CourseWorkMaterial

為了示範這項功能,您將新增路徑來修改特定串流項目。使用這個方法,驗證您是否可以存取及修改使用 API 建立的串流項目,以及老師透過 Google Classroom UI 建立的項目。

在本逐步操作說明中首次編輯的網頁中,新增另一個連結或按鈕。應會開啟新的路徑來修改 CourseWork 指派。

Python

提供的 Python 範例會修改在本逐步操作說明稍早修改的 /index 路徑。

<!-- /webapp/templates/index.html -->
<a href="modify-coursework-assignment.html">Create a CourseWork Assignment</a>

建立新的路徑來處理 CourseWork 相關路徑。這項資訊位於我們提供範例中的 coursework_routes.py 檔案中。

# Check that the user is signed in.
credentials = get_credentials()

if not credentials:
  return start_auth_flow("coursework_assignment_callback")

# Get the Google Classroom service.
classroom_service = get_classroom_service()

# The ID of the course to which the assignment will be added.
# Ordinarily, you'll prompt the user to specify which course to use. For
# simplicity, we use a hard-coded value in this example.
course_id = 1234567890  # TODO(developer) Replace with an actual course ID.
assignment_id = 1234567890  # TODO(developer) Replace with an actual assignment ID.

# Retrieve details about the CourseWork assignment.
get_coursework_response = (
    classroom_service.courses()
    .courseWork()
    .get(courseId=course_id, id=assignment_id)
    .execute()
)

# Alter the current title.
assignment_title = f"{get_coursework_response.get('title')} (Modified by API request)"

# Issue a request to modify the assignment.
modify_coursework_response = (
    classroom_service.courses()
    .courseWork()
    .patch(
        courseId=course_id,
        id=assignment_id,
        updateMask="title",
        body={"title": assignment_title},
    )
    .execute()
)

測試外掛程式

為簡化流程,提供的範例使用硬式編碼的課程和作業 ID。您可以使用教師憑證向 coursescourseWork 資源的 getlist 方法提出要求,取得這些 ID。建立 courseWork 指派時,系統也會在回應中傳回這些值。

請執行伺服器,然後前往索引頁面,並以老師使用者身分登入,但不要使用 Google Workspace for Education Teaching & Learning 或 Plus 授權。您可以透過測試網域的「管理控制台」切換使用者的授權狀態。按一下「建立課程作業」按鈕,然後開啟 Google Classroom UI,並確認已建立含有「連結教材」附件的作業。附件應顯示連結網頁的標題和網址。

測試外掛程式附件建立作業

返回索引頁面,並以具備 Google Workspace for Education Teaching & Learning 或 Plus 授權的老師身分登入。按一下「Create a CourseWork Assignment」按鈕,然後開啟 Google Classroom UI,確認已建立含有外掛程式附件的作業。附件應顯示外掛應用程式的名稱,以及程式碼中指定的標題。

測試指派項目修改

返回索引頁面,確認您是以具備 Teaching & Learning 或 Plus 授權的老師身分登入。按一下「修改課程作業」按鈕,然後返回 Google Classroom 使用者介面,確認作業名稱已變更。

恭喜!您已完成系列操作說明。