使用 Classroom API 管理评分周期

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

概览

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

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

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

许可要求

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

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

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

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

在 CourseWork 上设置评分周期 ID

无论教师被分配了什么许可,都可以在使用 API 创建或更新课程作业时添加 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。如果管理员不是课程的教师,则无法创建或修改课业。

管理 GradingPeriodSettings 资源

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

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

applyToExistingCoursework 布尔值是一种持久性设置,可让您将之前创建的课程作业整理到评分周期中,而无需进行单独的 API 调用来修改每个课程作业的 gradingPeriodId。如果将其设置为 True,当 courseWork.dueDate 落在现有评分周期的开始日期和结束日期之间时,Google 课堂会自动为所有现有作业设置 gradingPeriodId。如果未为课业设置截止日期,Google 课堂将使用 courseWork.scheduledTime。如果这两个字段都不存在,或者不与现有评分周期的开始日期和结束日期相符,则作业不会与任何评分周期相关联。

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

由于只有拥有特定许可的用户才能在 Google 课堂中创建和修改评分周期,因此 Classroom 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 后,系统会修改在评分周期的开始日期和结束日期之间所涵盖的任何现有课业作业的 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

读取评分周期设置

GradingPeriodSettings 使用 GetGradingPeriodSettings 端点进行读取。无论用户拥有何种许可,都可以查看课程中的评分周期设置。

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

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

为此,系统会读取当前的 GradingPeriodSettings,将新的评分周期添加到列表中,并将 applyToExistingCoursework 布尔值设为 False。请注意,已应用于现有课业作业的所有评分周期都不会被移除。在上面的示例中,“第 1 学期”和“第 2 学期”评分周期已应用于现有课程作业,如果在后续请求中将 applyToExistingCoursework 设置为 False,则不会从课程作业中移除这些评分周期。

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 所做的新更改不会应用于现有课程作业。在之前的 API 调用中,当布尔值设为 True 时,应用于课程作业的所有评分周期信息都不会被移除。一个有助于理解此布尔值设置的方法是:它支持将现有 Coursework 与您配置的评分周期相关联,但不支持移除 Coursework 与配置的评分周期之间的现有关联。

如果您删除或更改评分周期的标题,无论 applyToExistingCoursework 布尔值的设置如何,这些更改都将传播到所有现有的课程作业。

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

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

Python

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

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

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

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 字段。您可以使用课业端点读取和写入与课业相关联的评分周期。您可以通过以下三种方式管理此关联:

  • 自动基于日期的评分周期关联
  • 自定义关联的评分周期
  • 没有评分周期关联

1. 基于日期的评分周期关联

创建 CourseWork 时,您可以允许 Google 课堂为您处理评分周期关联。为此,请从 CourseWork 请求中省略 gradingPeriodId 字段。然后,在 CourseWork 请求中指定 dueDatescheduledTime 字段。如果 dueDate 落在现有评分周期的日期范围内,Google 课堂会在课业中设置该评分周期 ID。如果未指定 dueDate 字段,Google 课堂将根据 scheduledTime 字段确定 gradingPeriodId。如果未指定这两个字段,或者没有评分周期日期范围匹配项,则系统不会在课业中设置 gradingPeriodId

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

如果您想将课程作业与与 dueDatescheduledTime 不一致的评分周期相关联,可以在创建或更新课程作业时手动设置 gradingPeriodId 字段。如果您手动设置 gradingPeriodId,Google 课堂将不会执行基于日期的自动评分周期关联。

3. 未关联评分周期

如果您不希望将课程作业与任何评分周期相关联,请将 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()