使用 Classroom API 管理评分周期

本指南介绍了如何在 Google Classroom API 中使用评分周期端点。

概览

评分周期旨在将家庭作业、测验和项目整理到特定日期范围内。借助 Classroom API,开发者可以代表管理员和教师在 Google 课堂中创建、修改和读取评分周期。您还可以使用 Classroom API 在 CourseWork 上设置评分周期。

Classroom API 提供了两个端点,用于读取和写入课程中的评分周期信息:

  • GetGradingPeriodSettings:可让您读取课程中的评分周期设置。
  • UpdateGradingPeriodSettings:可让您添加、修改和删除评分周期,并将配置的评分周期应用于所有现有 CourseWork,从而管理课程中的评分周期设置。

许可要求

修改课程中的评分周期设置

如需使用 UpdateGradingPeriodSettings 端点在课程中创建、修改或删除评分周期,必须满足以下条件:

读取课程中的评分周期设置

无论课程的网域管理员和教师分配了哪种许可,他们都可以读取评分周期设置。这意味着允许代表任何网域管理员或教师向 GetGradingPeriodSettings 端点发送请求。

在 CourseWork 上设置评分周期 ID

无论课程教师获得哪种许可,在使用 API 创建或更新 CourseWork 时都可以添加 gradingPeriodId

检查用户是否符合设置评分周期的条件

您可以代表任何管理员或教师向 checkGradingPeriodsSetupEligibility 端点发出请求。使用此方法确定用户是否可以修改课程中的评分周期。

前提条件

本指南提供了 Python 格式的代码示例,并假定您已具备以下条件:

  • Google Cloud 项目。您可以按照 Python 快速入门中的说明设置一个。
  • 在项目的 OAuth 权限请求页面中添加了以下范围:
    • https://www.googleapis.com/auth/classroom.courses
    • https://www.googleapis.com/auth/classroom.coursework.students
  • 应修改评分周期的课程的 ID。课程所有者必须具有 Google Workspace 教育 Plus 版许可。
  • 通过 Google Workspace 教育 Plus 版许可访问教师或管理员的凭据。您需要有教师的凭据才能创建或修改 CourseWork。如果管理员不是课程的教师,则无法创建或修改 CourseWork。

管理 GradingPeriodSettings 资源

GradingPeriodSettings 资源包含单个 GradingPeriods 的列表和一个名为 applyToExistingCoursework 的布尔值字段。

GradingPeriods 列表表示课程中的所有单个评分周期。您必须为列表中的各个评分周期指定标题、开始日期和结束日期。课程中的每个评分周期必须具有唯一的标题,并且不同评分周期的开始日期和结束日期不能重叠。每个评分周期都有专属的 Classroom API 分配的标识符。

applyToExistingCoursework 布尔值是一项持久设置,可让您将之前创建的 CourseWork 整理到评分周期中,而无需单独进行 API 调用来修改每个 CourseWork 的 gradingPeriodId。如果设为 True,并且 courseWork.dueDate 在现有评分周期的开始日期和结束日期范围内,Google 课堂将自动为所有现有 CourseWork 设置 gradingPeriodId。如果 CourseWork 中没有设置截止日期,Google 课堂将使用 courseWork.scheduledTime。如果这两个字段都不存在,或在现有评分周期的开始日期和结束日期内没有匹配项,则 CourseWork 不会与任何评分周期关联。

确定用户是否可以修改课程中的评分周期设置

由于只有拥有特定许可的用户才能在 Google 课堂中创建和修改评分周期,因此 Google 课堂 API 提供了 checkGradingPeriodsSetupEligibility 端点,以帮助您主动确定用户是否能够向 UpdateGradingPeriodSettings 端点发出请求。

Python

def check_grading_period_setup_eligibility(classroom, course_id):
    """Checks whether a user is able to create and modify grading periods in a course."""
    try:
        grading_period_eligibility_response = classroom.courses().checkGradingPeriodsSetupEligibility(
          courseId=course_id, previewVersion="V1_20240401_PREVIEW").execute()

        # Retrieve the isGradingPeriodsSetupEligible boolean from the response.
        # If the boolean is `True`, the user is able to modify grading period settings in the course.
        is_grading_periods_eligible = grading_period_eligibility_response.get("isGradingPeriodsSetupEligible")
        return is_grading_periods_eligible
    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。请注意,updateMask 包含这两个字段。在响应中返回各个评分周期的 ID 后,请保存这些 ID。如有必要,您需要使用这些 ID 更新评分周期。

def create_grading_periods(classroom, 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.courses().updateGradingPeriodSettings(
          courseId=course_id,
          updateMask='gradingPeriods,applyToExistingCoursework',
          body=body,
          previewVersion="V1_20240401_PREVIEW"
        ).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

读取评分周期设置

系统使用 GetGradingPeriodSettings 端点读取 GradingPeriodSettings。无论拥有何种许可,任何用户都可以阅读课程中的评分周期设置。

Python

def get_grading_period_settings(classroom, course_id):
    """Read grading periods settings in a course."""
    try:
        gradingPeriodSettings = classroom.courses().getGradingPeriodSettings(
          courseId=course_id, previewVersion="V1_20240401_PREVIEW").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 或未知 ID 的评分周期会被视为错误

Python

以下代码将以本指南中的示例为基础进行构建。系统会创建一个新的评分周期,标题为“夏季”。在请求正文中,applyToExistingCoursework 布尔值设置为 False

为此,系统会读取当前的 GradingPeriodSettings,在列表中添加新的评分周期,并将 applyToExistingCoursework 布尔值设置为 False。请注意,系统不会移除已应用于现有 CourseWork 的任何评分周期。在前面的示例中,“学期 1”和“学期 2”的评分周期已应用于现有 CourseWork,并且如果在后续请求中将 applyToExistingCoursework 设为 False,则不会从 CourseWork 中移除。

def add_grading_period(classroom, 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.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework',
          previewVersion="V1_20240401_PREVIEW").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 布尔值的设置如何,这些更改都将传播到所有现有 CourseWork 中。

更新列表中的单个评分周期

如需修改与现有评分周期关联的某些数据,请在包含修改后数据的列表中添加现有评分周期的 ID。

Python

在此示例中,系统将修改“夏季”评分周期的结束日期。applyToExistingCoursework 字段将设置为 True。请注意,将此布尔值设置为 True 会将所有已配置的评分周期应用到现有 CourseWork。在上一个 API 请求中,该布尔值设置为 False,这样“夏季”评分周期不会应用于现有的 CourseWork。现在,此布尔值字段已设置为 True,“Summer”评分周期将应用于所有匹配的现有 CourseWork。

def update_existing_grading_period(classroom, 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.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods,applyToExistingCoursework',
          previewVersion="V1_20240401_PREVIEW").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

如需继续本指南中的示例,请省略评分周期“Summer”,以将其删除。

def delete_grading_period(classroom, 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.courses().updateGradingPeriodSettings(
          courseId=course_id, body=body, updateMask='gradingPeriods',
          previewVersion="V1_20240401_PREVIEW").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 时,您可以允许 Google 课堂为您处理评分周期关联。为此,请在 CourseWork 请求中省略 gradingPeriodId 字段。然后,在 CourseWork 请求中指定 dueDatescheduledTime 字段。如果 dueDate 在现有的评分周期日期范围内,Google 课堂将在 CourseWork 中设置该评分周期 ID。如果未指定 dueDate 字段,Google 课堂将根据 scheduledTime 字段确定 gradingPeriodId。如果这两个字段均未指定,或者没有评分周期日期范围匹配,则 CourseWork 中不会设置任何 gradingPeriodId

2. 自定义关联的评分周期

如果您希望将 CourseWork 与与 dueDatescheduledTime 对应的评分周期不同的评分周期相关联,则可以在创建或更新 CourseWork 时手动设置 gradingPeriodId 字段。如果您手动设置 gradingPeriodId,Google 课堂将不会执行基于日期的自动评分周期关联。

3. 未关联评分周期

如果您根本不希望 CourseWork 与任何评分周期关联,请将 CourseWork 请求中的 gradingPeriodId 字段设置为空字符串 (gradingPeriodId: "")。

如果更新截止日期,评分周期 ID 会出现什么情况?

如果您要更新 CourseWork dueDate 字段,并且希望保留自定义或无评分周期关联,则应在 updateMask 和请求正文中添加 dueDategradingPeriodId。这将告知 Google 课堂不要使用与新 dueDate 一致的评分周期替换 gradingPeriodId

Python

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