使用 Classroom API 管理評分週期

本指南說明如何使用 Google Classroom API 中的評分週期端點。

總覽

評分週期可將作業、測驗和專案歸入特定日期範圍。開發人員可透過 Classroom API,代表管理員和老師在 Classroom 中建立、修改及讀取評分週期。您也可以使用 Classroom API,在 CourseWork 中設定評分週期。

Classroom API 提供兩個端點,可讀取及寫入課程中的評分週期資訊:

  • GetGradingPeriodSettings:可讓您讀取課程中的評分期間設定。
  • UpdateGradingPeriodSettings:可讓您管理課程中的評分週期設定,包括新增、修改及刪除評分週期,以及將設定的評分週期套用至所有現有作業。

授權與資格規定

修改課程中的評分週期設定

如要使用 UpdateGradingPeriodSettings 端點在課程中建立、修改或刪除評分週期,必須符合下列條件:

讀取課程中的評分週期設定

無論獲派哪種授權,網域管理員和課程老師都可以讀取評分週期設定。也就是說,任何網域管理員或老師都可以代表提出對 GetGradingPeriodSettings 端點的要求。

在 CourseWork 上設定評分週期 ID

無論老師的授權為何,只要使用 API 建立或更新 CourseWork,就能加入 gradingPeriodId

檢查使用者是否符合設定評分週期的資格

系統允許代表任何管理員或老師,向 userProfiles.checkUserCapability 端點提出要求。用來判斷使用者是否可以修改評分週期。

必要條件

本指南提供 Python 程式碼範例,並假設您已具備下列條件:

  • Google Cloud 專案。如要設定,請按照 Python 快速入門中的操作說明進行。
  • 在專案的 OAuth 同意畫面中新增下列範圍:
    • https://www.googleapis.com/auth/classroom.courses
    • https://www.googleapis.com/auth/classroom.coursework.students
  • 要修改評分週期的課程 ID。課程擁有者必須具備 Google Workspace for Education Plus 授權。
  • 存取老師或管理員的憑證,並取得 Google Workspace for Education Plus 授權。您必須具備老師的憑證,才能建立或修改 CourseWork。如果管理員不是課程老師,就無法建立或修改作業。

管理 GradingPeriodSettings 資源

GradingPeriodSettings 資源包含個別 GradingPeriods 的清單,以及名為 applyToExistingCoursework 的布林欄位。

請確認清單中的每個 GradingPeriods 都符合下列規定:

  • 標題、開始日期和結束日期:每個評分期間都必須有標題、開始日期和結束日期。
  • 不重複的名稱:每個評分週期都必須有不重複的名稱,且不得與課程中的其他評分週期相同。
  • 日期不得重疊:每個評分期間的開始或結束日期,不得與課程中的任何其他評分期間重疊。
  • 時間順序:評分週期必須依開始和結束日期,以時間順序排列。

建立評分週期時,系統會為每個週期指派 Classroom API ID。

applyToExistingCoursework 布林值是持續性設定,可讓您將先前建立的 CourseWork 歸入評分週期,不必為每個 CourseWork 分別發出 API 呼叫來修改 gradingPeriodId。如果設為 True,當 courseWork.dueDate 落在現有評分週期的開始和結束日期之間時,Classroom 會自動為所有現有 CourseWork 設定 gradingPeriodId。如果 CourseWork 未設定截止日期,Classroom 會使用 courseWork.scheduledTime。如果沒有這兩個欄位,或現有評分期間的開始和結束日期不相符,CourseWork 就不會與任何評分期間建立關聯。

決定使用者是否可以在課程中修改評分週期設定

Classroom API 提供 userProfiles.checkUserCapability 端點,可協助您主動判斷使用者是否能向 UpdateGradingPeriodSettings 端點提出要求。

Python

def check_grading_periods_update_capability(classroom_service, course_id):
    """Checks whether a user is able to create and modify grading periods in a course."""
    try:
        capability = classroom_service.userProfiles().checkUserCapability(
          userId="me",
          capability="UPDATE_GRADING_PERIOD_SETTINGS",
           # Required while the checkUserCapability method is available in the Developer Preview Program.
          previewVersion="V1_20240930_PREVIEW"
        ).execute()

        # Retrieve the `allowed` boolean from the response.
        if capability.get("allowed"):
          print("User is allowed to update grading period settings in the course.")
        else:
          print("User is not allowed to update grading period settings in the course.")
    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

新增評分週期

現在您已確定使用者有權修改課程的評分週期設定,可以開始向 UpdateGradingPeriodSettings 端點發出要求。無論是新增個別評分週期、修改現有評分週期,還是刪除評分週期,對 GradingPeriodSettings 資源所做的任何修改,都是使用 UpdateGradingPeriodSettings 端點執行。

Python

在下列範例中,gradingPeriodSettings 資源經過修改,納入兩個評分週期。applyToExistingCoursework 布林值設為 True,這會修改任何現有 CourseWork 的 gradingPeriodId,這些 CourseWork 落在某個評分週期的開始和結束日期之間。請注意,updateMask 包含這兩個欄位。回應傳回個別評分週期 ID 後,請儲存這些 ID。如有需要,您可以使用這些 ID 更新評分週期。

def create_grading_periods(classroom_service, course_id):
    """
    Create grading periods in a course and apply the grading periods
    to existing courseWork.
    """
    try:
        body = {
          "gradingPeriods": [
            {
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": True
        }
        gradingPeriodSettingsResponse = classroom_service.courses().updateGradingPeriodSettings(
          courseId=course_id,
          updateMask='gradingPeriods,applyToExistingCoursework',
          body=body
        ).execute();

        print(f"Grading period settings updated.")
        return gradingPeriodSettingsResponse

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

讀取評分週期設定

GradingPeriodSettings 是透過 GetGradingPeriodSettings 端點讀取。無論授權為何,所有使用者都能在課程中讀取評分週期設定。

Python

def get_grading_period_settings(classroom_service, course_id):
    """Read grading periods settings in a course."""
    try:
        gradingPeriodSettings = classroom_service.courses().getGradingPeriodSettings(
          courseId=course_id).execute()
        return gradingPeriodSettings
    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

將個別評分週期新增至清單

如要更新個別評分週期,請按照「讀取 - 修改 - 寫入」模式操作。這代表您應該:

  1. 使用 GetGradingPeriodSettings 端點,讀取 GradingPeriodSettings 資源中的評分週期清單。
  2. 對評分週期清單進行所選修改。
  3. 在要求中將新的評分期間清單傳送至 UpdateGradingPeriodSettings

這個模式可協助您確保課程中的個別評分週期名稱不重複,且評分週期的開始與結束日期不會重疊。

更新評分週期清單時,請注意下列規則:

  1. 新增至清單但沒有 ID 的評分週期會視為新增項目
  2. 清單中缺少的評分週期會視為刪除
  3. 如果評分週期已有 ID,但資料經過修改,則視為編輯。未修改的屬性會維持原狀。
  4. 如果評分週期含有新的或不明 ID,系統會視為錯誤

Python

下列程式碼會以本指南中的範例為基礎。系統會建立名為「夏季」的新評分週期。要求主體中的 applyToExistingCoursework 布林值設為 False

如要這麼做,請讀取目前的 GradingPeriodSettings、在清單中新增評分週期,並將 applyToExistingCoursework 布林值設為 False。請注意,已套用至現有作業的評分期間不會移除。在上述範例中,「第 1 學期」和「第 2 學期」的評分週期已套用至現有 CourseWork,如果後續要求將 applyToExistingCoursework 設為 False,系統不會從 CourseWork 移除這些週期。

def add_grading_period(classroom_service, course_id):
    """
    A new grading period is added to the list, but it is not applied to existing courseWork.
    """
    try:
        # Use the `GetGradingPeriodSettings` endpoint to retrieve the existing
        # grading period IDs. You will need to include these IDs in the request
        # body to make sure existing grading periods aren't deleted.
        body = {
          "gradingPeriods": [
            {
              # Specify the ID to make sure the grading period is not deleted.
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              # Specify the ID to make sure the grading period is not deleted.
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            },
            {
              # Does not include an ID because this grading period is an addition.
              "title": "Summer",
              "start_date": {
                "day": 1,
                "month": 6,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 8,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": False
        }

        gradingPeriodSettings = classroom_service.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework').execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

applyToExistingCoursework 布林欄位的實用指標

請務必記得,applyToExistingCoursework 布林值會保留,也就是說,如果布林值在先前的 API 呼叫中設為 True 且未變更,後續的評分週期更新會套用至現有 CourseWork。

請注意,如果您在對 UpdateGradingPeriodSettings 的要求中,將這個布林值從 True 變更為 False,則只有您對 GradingPeriodSettings 所做的新變更不會套用至現有 CourseWork。如果布林值設為 True,系統不會移除先前 API 呼叫中套用至 CourseWork 的任何評分週期資訊。這項布林值設定可協助您將現有 CourseWork 與已設定的評分週期建立關聯,但無法移除 CourseWork 與已設定評分週期之間的現有關聯。

如果刪除或變更評分週期名稱,系統會將這些變更套用至所有現有作業,無論 applyToExistingCoursework 布林值設定為何。

更新清單中的個別評分週期

如要修改與現有評分週期相關聯的部分資料,請在清單中加入現有評分週期的 ID,並附上修改後的資料。

Python

在本例中,系統會修改「夏季」評分週期的結束日期。「applyToExistingCoursework」欄位會設為 True。注意:將這個布林值設為 True,會將所有已設定的評分週期套用至現有 CourseWork。在先前的 API 要求中,布林值設為 False,因此「夏季」評分週期不會套用至現有 CourseWork。現在這個布林值欄位已設為 True,系統會將「夏季」評分週期套用至所有相符的現有 CourseWork。

def update_existing_grading_period(classroom_service, course_id):
    """
    An existing grading period is updated.
    """
    try:
        # Use the `GetGradingPeriodSettings` endpoint to retrieve the existing
        # grading period IDs. You will need to include these IDs in the request
        # body to make sure existing grading periods aren't deleted.
        body = {
          "gradingPeriods": [
            {
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            },
            {
              # The end date for this grading period will be modified from August 31, 2024 to September 10, 2024.
              # Include the grading period ID in the request along with the new data.
              "id": "SUMMER_GRADING_PERIOD_ID",
              "title": "Summer",
              "start_date": {
                "day": 1,
                "month": 6,
                "year": 2024
              },
              "end_date": {
                "day": 10,
                "month": 9,
                "year": 2024
              }
            }
          ],
          "applyToExistingCoursework": True
        }

        gradingPeriodSettings = classroom_service.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework').execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

刪除個別評分週期

如要刪除評分週期,請從清單中省略該週期。請注意,無論 applyToExistingCoursework 設定為何,如果刪除評分期間,系統也會一併刪除 CourseWork 中對該評分期間的所有參照。

Python

如要繼續本指南中的範例,請省略「夏季」這個評分週期,藉此刪除該週期。

def delete_grading_period(classroom_service, course_id):
    """
    An existing grading period is deleted.
    """
    try:
        body = {
          "gradingPeriods": [
            {
              "id": "FIRST_SEMESTER_GRADING_PERIOD_ID",
              "title": "First Semester",
              "start_date": {
                "day": 1,
                "month": 9,
                "year": 2023
              },
              "end_date": {
                "day": 15,
                "month": 12,
                "year": 2023
              }
            },
            {
              "id": "SECOND_SEMESTER_GRADING_PERIOD_ID",
              "title": "Second Semester",
              "start_date": {
                "day": 15,
                "month": 1,
                "year": 2024
              },
              "end_date": {
                "day": 31,
                "month": 5,
                "year": 2024
              }
            }
          ]
        }

        gradingPeriodSettings = classroom_service.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods').execute()
        return gradingPeriodSettings

    except HttpError as error:
        # Handle errors as appropriate for your application.
        print(f"An error occurred: {error}")
        return error

管理 CourseWork 的 gradingPeriodId 欄位

CourseWork 資源包含 gradingPeriodId 欄位。您可以使用 CourseWork 端點讀取及寫入與 CourseWork 相關聯的評分週期。管理這項關聯的方式有三種:

  • 根據日期自動將作業與評分期間建立關聯
  • 自訂相關聯的評分週期
  • 沒有評分週期關聯

1. 以日期為準的評分週期關聯

建立 CourseWork 時,您可以允許 Classroom 為您處理評分週期關聯。如要這麼做,請從 CourseWork 要求中省略 gradingPeriodId 欄位。然後在 CourseWork 要求中指定 dueDatescheduledTime 欄位。如果 dueDate 落在現有評量期間的日期範圍內,Classroom 會在 CourseWork 上設定該評量期間 ID。如未指定 dueDate 欄位,Classroom 會根據 scheduledTime 欄位判斷 gradingPeriodId。如果未指定任一欄位,或沒有相符的評分週期日期範圍,系統就不會在 CourseWork 上設定 gradingPeriodId

2. 自訂相關聯的評分週期

如要將 CourseWork 與其他評分週期建立關聯,而非與 dueDatescheduledTime 對應的週期建立關聯,您可以在建立或更新 CourseWork 時,手動設定 gradingPeriodId 欄位。如果手動設定 gradingPeriodId,Classroom 就不會自動根據日期將作業與評分週期建立關聯。

3. 沒有評分週期關聯

如果不想將 CourseWork 與任何評分週期建立關聯,請將 CourseWork 要求的 gradingPeriodId 欄位設為空字串 (gradingPeriodId: "")。

如果您使用 Go 程式設計語言,且不想設定評分週期,也應在要求主體中加入 ForceSendFields 欄位。使用 Go 用戶端程式庫時,由於所有欄位都有 omitempty 欄位標記,因此 API 要求會省略預設值。ForceSendFields 欄位會略過這項設定,並傳送空字串,表示您不希望為該 CourseWork 設定任何評分週期。詳情請參閱 Google API Go 用戶端程式庫說明文件

Go

courseWork := &classroom.CourseWork{
  Title: "Homework questions",
  WorkType: "ASSIGNMENT",
  State: "DRAFT",
  // ...other CourseWork fields...
  GradingPeriodId: "",
  ForceSendFields: []string{"GradingPeriodId"},
}

如果更新截止日期,評分期間 ID 會發生什麼情況?

如要更新 CourseWork dueDate 欄位,並保留自訂或沒有評分週期關聯,請在 updateMask 和要求內文中加入 dueDategradingPeriodId。這樣一來,Classroom 就不會根據新的 dueDate,覆寫相符的評分週期 gradingPeriodId

Python

body = {
  "dueDate": {
    "month": 6,
    "day": 10,
    "year": 2024
  },
  "dueTime": {
    "hours": 7
  },
  "gradingPeriodId": "<INSERT-GRADING-PERIOD-ID-OR-EMPTY-STRING>"
}
courseWork = classroom_service.courses().courseWork().patch(
  courseId=course_id, id=coursework_id, body=body,
  updateMask='dueDate,dueTime,gradingPeriodId') # include the gradingPeriodId field in the updateMask
.execute()