您的用户是通过 Google Meet 使用 Google 课堂吗?请查看 Apps 脚本快速入门 - 了解如何在 Google Meet 课程中查看学生出席情况

管理课程作业和成绩

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

Google 课堂界面支持种类型的课业:作业、测验作业、简答题、选择题和资料。Classroom API 目前支持三种类型,即该 API 的 CourseWorkType:作业、简答题和选择题。

如需使用此功能,您可以使用 CourseWork 资源,该资源表示为特定课程中分配给学生的作业或题目,包括任何其他资料和详细信息,如截止日期或最高分数。

除了 CourseWork 资源外,您还可以使用 StudentSubmission 资源管理已完成的分配。以下部分更详细地介绍了这些内容。

创建作业

您只能代表课程的教师创建作业,尝试在学生的课程中创建作业会产生 403 PERMISSION_DENIED 错误。同样,网域管理员也无法为他们不教授的课程创建作业,尝试通过 API 创建课程也会导致 403 PERMISSION_DENIED 错误。

使用 courses.courseWork.create 方法创建分配时,您可以将链接作为 materials 附加,如以下示例代码所示:

Java

classroom/snippets/src/main/java/CreateCourseWork.java
CourseWork courseWork = null;
try {
  // Create a link to add as a material on course work.
  Link articleLink = new Link()
      .setTitle("SR-71 Blackbird")
      .setUrl("https://www.lockheedmartin.com/en-us/news/features/history/blackbird.html");

  // Create a list of Materials to add to course work.
  List<Material> materials = Arrays.asList(new Material().setLink(articleLink));

  /* Create new CourseWork object with the material attached.
  Set workType to `ASSIGNMENT`. Possible values of workType can be found here:
  https://developers.google.com/classroom/reference/rest/v1/CourseWorkType
  Set state to `PUBLISHED`. Possible values of state can be found here:
  https://developers.google.com/classroom/reference/rest/v1/courses.courseWork#courseworkstate */
  CourseWork content = new CourseWork()
      .setTitle("Supersonic aviation")
      .setDescription("Read about how the SR-71 Blackbird, the world’s fastest and "
          + "highest-flying manned aircraft, was built.")
      .setMaterials(materials)
      .setWorkType("ASSIGNMENT")
      .setState("PUBLISHED");

  courseWork = service.courses().courseWork().create(courseId, content)
      .execute();

  /* Prints the created courseWork. */
  System.out.printf("CourseWork created: %s\n", courseWork.getTitle());
} catch (GoogleJsonResponseException e) {
  //TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf("The courseId does not exist: %s.\n", courseId);
  } else {
    throw e;
  }
  throw e;
} catch (Exception e) {
  throw e;
}
return courseWork;

Python

classroom/snippets/classroom_create_coursework.py
from __future__ import print_function

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_create_coursework(course_id):

    """
    Creates the coursework the user has access to.
    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """

    creds, _ = google.auth.default()
    # pylint: disable=maybe-no-member

    try:
        service = build('classroom', 'v1', credentials=creds)
        coursework = {
            'title': 'Ant colonies',
            'description': '''Read the article about ant colonies
                              and complete the quiz.''',
            'materials': [
                {'link': {'url': 'http://example.com/ant-colonies'}},
                {'link': {'url': 'http://example.com/ant-quiz'}}
            ],
            'workType': 'ASSIGNMENT',
            'state': 'PUBLISHED',
        }
        coursework = service.courses().courseWork().create(
            courseId=course_id, body=coursework).execute()
        print(f"Assignment created with ID {coursework.get('id')}")
        return coursework

    except HttpError as error:
        print(f"An error occurred: {error}")
        return error


if __name__ == '__main__':
    # Put the course_id of course whose coursework needs to be created,
    # the user has access to.
    classroom_create_coursework(453686957652)

结果包括一个由服务器分配的标识符,可用于在其他 API 请求中引用该分配。

要在通过 Classroom API 创建的作业中包含关联的资料,请使用链接资源指定目标网址。Google 课堂会自动提取标题和缩略图。 Classroom API 还以原生方式支持 Google 云端硬盘和 YouTube 资料,这些资料可以采用类似的方式添加到 DriveFile 资源YouTubeVideo 资源中。

如需指定截止日期,请将 dueDatedueTime 字段设置为相应的世界协调时间 (UTC)。截止日期必须是将来的日期。

检索作业和题目

您可以检索相应课程的学生和教师的作业或题目,也可以由网域管理员检索。如需检索特定作业或题目,请使用 course.courseWork.get。如需检索所有作业或题目(可以选择匹配某些条件),请使用 courses.courseWork.list。

所需范围取决于发出请求的用户在课程中的角色。如果用户是学生,请使用以下范围之一:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

如果用户是教师或网域管理员,请使用以下范围之一:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

拥有检索作业或题目的权限并不意味着可以访问资料或资料元数据。实际上,这意味着,如果管理员不是课程的成员,则可能不会看到附加的云端硬盘文件的标题。如果要允许管理员访问用户文件,请参阅全网域授权指南。

管理学生的回复

StudentSubmission 资源表示学生的作业或题目的完成成绩和成绩。创建新问题或作业时,系统会为每个学生隐式创建一个 StudentSubmission 资源。

以下部分介绍了管理学生回复的常见操作。

检索学生回复

学生可以检索自己的提交内容,教师可以检索其课程中所有学生的提交内容,而网域管理员可以检索其网域内所有学生的所有提交内容。每个学生提交的内容都分配有一个标识符;如果您知道该标识符,请使用 courses.courseWork.studentSubmissions.get 进行检索。

使用 courses.courseWork.studentSubmissions.list 方法获取符合某些条件的 StudentSubmission 资源,如以下示例所示:

Java

classroom/snippets/src/main/java/ListSubmissions.java
List<StudentSubmission> studentSubmissions = new ArrayList<>();
String pageToken = null;

try {
  do {
    ListStudentSubmissionsResponse response =
        service
            .courses()
            .courseWork()
            .studentSubmissions()
            .list(courseId, courseWorkId)
            .setPageToken(pageToken)
            .execute();

    /* Ensure that the response is not null before retrieving data from it to avoid errors. */
    if (response.getStudentSubmissions() != null) {
      studentSubmissions.addAll(response.getStudentSubmissions());
      pageToken = response.getNextPageToken();
    }
  } while (pageToken != null);

  if (studentSubmissions.isEmpty()) {
    System.out.println("No student submission found.");
  } else {
    for (StudentSubmission submission : studentSubmissions) {
      System.out.printf(
          "Student id (%s), student submission id (%s)\n",
          submission.getUserId(), submission.getId());
    }
  }
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s) or courseWorkId (%s) does not exist.\n", courseId, courseWorkId);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmissions;

Python

classroom/snippets/classroom_list_submissions.py
from __future__ import print_function

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_list_submissions(course_id, coursework_id):
    """
    Creates the courses the user has access to.
    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """

    creds, _ = google.auth.default()
    # pylint: disable=maybe-no-member
    submissions = []
    page_token = None

    try:
        service = build('classroom', 'v1', credentials=creds)
        while True:
            coursework = service.courses().courseWork()
            response = coursework.studentSubmissions().list(
                pageToken=page_token,
                courseId=course_id,
                courseWorkId=coursework_id,
                pageSize=10).execute()
            submissions.extend(response.get('studentSubmissions', []))
            page_token = response.get('nextPageToken', None)
            if not page_token:
                break

        if not submissions:
            print('No student submissions found.')

        print('Student Submissions:')
        for submission in submissions:
            print(f"Submitted at:"
                  f"{(submission.get('id'), submission.get('creationTime'))}")

    except HttpError as error:
        print(f"An error occurred: {error}")
        submissions = None
    return submissions


if __name__ == '__main__':
    # Put the course_id and coursework_id of course whose list needs to be
    # submitted.
    classroom_list_submissions(453686957652, 466086979658)

通过指定 userId 参数来检索属于特定学生的 StudentSubmission 资源,如以下示例所示:

Java

classroom/snippets/src/main/java/ListStudentSubmissions.java
List<StudentSubmission> studentSubmissions = new ArrayList<>();
String pageToken = null;

try {
  do {
    // Set the userId as a query parameter on the request.
    ListStudentSubmissionsResponse response =
        service
            .courses()
            .courseWork()
            .studentSubmissions()
            .list(courseId, courseWorkId)
            .setPageToken(pageToken)
            .set("userId", userId)
            .execute();

    /* Ensure that the response is not null before retrieving data from it to avoid errors. */
    if (response.getStudentSubmissions() != null) {
      studentSubmissions.addAll(response.getStudentSubmissions());
      pageToken = response.getNextPageToken();
    }
  } while (pageToken != null);

  if (studentSubmissions.isEmpty()) {
    System.out.println("No student submission found.");
  } else {
    for (StudentSubmission submission : studentSubmissions) {
      System.out.printf("Student submission: %s.\n", submission.getId());
    }
  }
} catch (GoogleJsonResponseException e) {
  // TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf(
        "The courseId (%s), courseWorkId (%s), or userId (%s) does " + "not exist.\n",
        courseId, courseWorkId, userId);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmissions;

Python

classroom/snippets/classroom_list_student_submissions.py
from __future__ import print_function

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def classroom_list_student_submissions(course_id, coursework_id, user_id):
    """
    Creates the courses the user has access to.
    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """

    creds, _ = google.auth.default()
    # pylint: disable=maybe-no-member
    submissions = []
    page_token = None

    try:
        service = build('classroom', 'v1', credentials=creds)
        while True:
            coursework = service.courses().courseWork()
            response = coursework.studentSubmissions().list(
                pageToken=page_token,
                courseId=course_id,
                courseWorkId=coursework_id,
                userId=user_id).execute()
            submissions.extend(response.get('studentSubmissions', []))
            page_token = response.get('nextPageToken', None)
            if not page_token:
                break

        if not submissions:
            print('No student submissions found.')

        print('Student Submissions:')
        for submission in submissions:
            print(f"Submitted at:"
                  f"{(submission.get('id'), submission.get('creationTime'))}")

    except HttpError as error:
        print(f"An error occurred: {error}")
    return submissions


if __name__ == '__main__':
    # Put the course_id, coursework_id and user_id of course whose list needs
    # to be submitted.
    classroom_list_student_submissions(453686957652, 466086979658, "me")

学生可通过 Google Admin SDK 返回的用户唯一 ID 或电子邮件地址来标识。当前用户还可以使用 "me" 简写形式引用自己的 ID。

用户还可以获取课程中所有作业的学生提交内容。为此,请使用字面量 "-" 作为 courseWorkId,如以下示例所示:

Java

service.courses().courseWork().studentSubmissions()
    .list(courseId, "-")
    .set("userId", userId)
    .execute();

Python

service.courses().courseWork().studentSubmissions().list(
    courseId=<course ID or alias>,
    courseWorkId='-',
    userId=<user ID>).execute()

所需范围取决于发出请求的用户在课程中的角色。如果用户是教师或网域管理员,请使用以下范围:

  • https://www.googleapis.com/auth/classroom.coursework.students.readonly
  • https://www.googleapis.com/auth/classroom.coursework.students

如果用户是学生,请使用以下范围:

  • https://www.googleapis.com/auth/classroom.coursework.me.readonly
  • https://www.googleapis.com/auth/classroom.coursework.me

拥有检索学生提交的作业的权限并不意味着可以访问附件或附件元数据。实际上,这意味着,如果管理员不是课程成员,则可能不会看到附加的云端硬盘文件的标题。如果要允许管理员访问用户文件,请参阅全网域授权指南。

在学生回复中添加附件

您可以通过附加 LinkDriveFileYouTubeVideo 资源,将链接附加到学生提交的内容中。这可通过 courses.courseWork.studentSubmissions.modifyAttachments 完成,如以下示例所示:

Java

classroom/snippets/src/main/java/ModifyAttachmentsStudentSubmission.java
StudentSubmission studentSubmission = null;
try {
  // Create ModifyAttachmentRequest object that includes a new attachment with a link.
  Link link = new Link().setUrl("https://en.wikipedia.org/wiki/Irrational_number");
  Attachment attachment = new Attachment().setLink(link);
  ModifyAttachmentsRequest modifyAttachmentsRequest = new ModifyAttachmentsRequest()
      .setAddAttachments(Arrays.asList(attachment));

  // The modified studentSubmission object is returned with the new attachment added to it.
  studentSubmission = service.courses().courseWork().studentSubmissions().modifyAttachments(
      courseId, courseWorkId, id, modifyAttachmentsRequest)
      .execute();

  /* Prints the modified student submission. */
  System.out.printf("Modified student submission attachments: '%s'.\n", studentSubmission
      .getAssignmentSubmission()
      .getAttachments());
} catch (GoogleJsonResponseException e) {
  //TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf("The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
        + "not exist.\n", courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch(Exception e) {
  throw e;
}
return studentSubmission;

Python

classroom/snippets/classroom_add_attachment.py

def classroom_add_attachment(course_id, coursework_id, submission_id):
    """
    Adds attachment to existing course with specific course_id.
    Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity
    for guides on implementing OAuth2 for the application.
    """
    creds, _ = google.auth.default()
    # pylint: disable=maybe-no-member
    request = {
        'addAttachments': [
            {'link': {'url': 'http://example.com/quiz-results'}},
            {'link': {'url': 'http://example.com/quiz-reading'}}
        ]
    }

    try:
        service = build('classroom', 'v1', credentials=creds)
        while True:
            coursework = service.courses().courseWork()
            coursework.studentSubmissions().modifyAttachments(
                courseId=course_id,
                courseWorkId=coursework_id,
                id=submission_id,
                body=request).execute()

    except HttpError as error:
        print(f"An error occurred: {error}")


if __name__ == '__main__':
    # Put the course_id, coursework_id and submission_id of course in which
    # attachment needs to be added.
    classroom_add_attachment('course_id', 'coursework_id', "me")

链接附件由目标网址定义;Google 课堂会自动提取标题和缩略图。如需了解其他材料,请访问相应的参考页面。

StudentSubmission 只能由课程教师或拥有它的学生修改。只有在学生提交的 CourseWorkTypeASSIGNMENT 时,您才能附加 Materials

所需范围取决于发出请求的用户在课程中的角色。如果用户是教师,请使用以下范围:

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

如果用户是学生,请使用以下范围:

  • https://www.googleapis.com/auth/classroom.coursework.me

管理学生回复状态

学生的答案可以取消提交、上交或发回。StudentSubmission 中的状态字段指示当前状态。如需更改状态,请调用以下方法之一:

所有这些方法都会采用空的正文。例如:

Java

classroom/snippets/src/main/java/ReturnStudentSubmission.java
try {
  service.courses().courseWork().studentSubmissions()
      .classroomReturn(courseId, courseWorkId, id, null)
      .execute();
} catch (GoogleJsonResponseException e) {
  //TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf("The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
        + "not exist.\n", courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}

Python

service.courses().courseWork().studentSubmission().turnIn(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    body={}).execute()

只有拥有 StudentSubmission 的学生才能上交或收回此作业。 只能回收已交的作业。课程教师只能返回处于已交状态的 StudentSubmission

为学生回答评分

StudentSubmission 资源有两个用于存储成绩的字段:assignedGrade(这是报告给学生的成绩)和 draftGrade(一个仅供教师使用的暂定成绩)。使用 courses.courseWork.studentSubmissions.patch 更新这些字段,通过字段掩码包含适当的字段,如以下示例所示。

Java

classroom/snippets/src/main/java/PatchStudentSubmission.java
StudentSubmission studentSubmission = null;
try {
  // Updating the draftGrade and assignedGrade fields for the specific student submission.
  StudentSubmission content = service.courses().courseWork().studentSubmissions()
      .get(courseId, courseWorkId, id)
      .execute();
  content.setAssignedGrade(90.00);
  content.setDraftGrade(80.00);

  // The updated studentSubmission object is returned with the new draftGrade and assignedGrade.
  studentSubmission = service.courses().courseWork().studentSubmissions()
      .patch(courseId, courseWorkId, id, content)
      .set("updateMask", "draftGrade,assignedGrade")
      .execute();

  /* Prints the updated student submission. */
  System.out.printf("Updated student submission draft grade (%s) and assigned grade (%s).\n",
      studentSubmission.getDraftGrade(),
      studentSubmission.getAssignedGrade());
} catch (GoogleJsonResponseException e) {
  //TODO (developer) - handle error appropriately
  GoogleJsonError error = e.getDetails();
  if (error.getCode() == 404) {
    System.out.printf("The courseId (%s), courseWorkId (%s), or studentSubmissionId (%s) does "
        + "not exist.\n", courseId, courseWorkId, id);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmission;

Python

studentSubmission = {
  'assignedGrade': 99,
  'draftGrade': 80
}
service.courses().courseWork().studentSubmissions().patch(
    courseId=<course ID or alias>,
    courseWorkId=<courseWork ID>,
    id=<studentSubmission ID>,
    updateMask='assignedGrade,draftGrade',
    body=studentSubmission).execute()

使用 Google 课堂界面时,教师必须先保存初始成绩,然后才能为其评分。然后,可以将分配的成绩发回给学生。应用需要模拟此行为。您的应用可以通过以下两种方式之一为学生的作业评分:

  • 仅分配 draftGrade。例如,您可以让教师在完成评分前手动查看成绩,这种做法非常有用。学生无法查看初始成绩。

  • 布置draftGradeassignedGrade,以全面评分作业。

列出已分配的成绩

通过浏览 courses.courseWork.studentSubmissions.list 方法的响应对象,您可以列出特定课程项的所有成绩:

Java

ListStudentSubmissionsResponse response = service.courses().courseWork().studentSubmissions()
    .list(courseId, courseWorkId)
    .execute();

if (response.getStudentSubmissions() != null) {
  List<StudentSubmission> submissionList = response.getStudentSubmissions();

  for (StudentSubmission submission : submissionList) {
    System.out.printf("User ID %s, Assigned grade: %s", submission.getUserId(),
        submission.getAssignedGrade());
  }
} else {
  System.out.println("No submissions found.");
}

Python

response = coursework.studentSubmissions().list(
    courseId=course_id,
    courseWorkId=coursework_id,
    pageSize=10).execute()
submissions.extend(response.get('studentSubmissions', []))

if not submissions:
    print('No student submissions found.')

print('Student Submissions:')
for submission in submissions:
    print(f"Submitted at:"
          f"{(submission.get('userId'), submission.get('assignedGrade'))}")