학습 과제 관리

클래스룸 UI는 과제, 퀴즈 과제, 단답형 질문, 객관식 질문, 자료 등 5가지 유형의 수업 과제를 지원합니다. Classroom API는 현재 과제, 단답형 질문, 객관식 질문 등 이러한 유형 중 세 가지를 지원합니다. 이러한 유형은 API에서 CourseWorkType라고 합니다.

이 기능에 액세스하려면 마감일 또는 최대 점수와 같은 추가 자료와 세부정보를 포함하여 특정 과정의 학생에게 할당된 과제 또는 질문을 나타내는 CourseWork 리소스를 사용하면 됩니다.

CourseWork 리소스 외에도 StudentSubmission 리소스를 사용하여 완료된 과제를 관리할 수 있습니다. 다음 섹션에서는 이를 자세히 설명합니다.

과제 만들기

과제는 강의의 교사를 대신하여 만들 수 있습니다. 학생을 대신하여 강의에서 과제를 만들려고 하면 403 PERMISSION_DENIED 오류가 발생합니다. 마찬가지로 도메인 관리자도 자신이 가르치지 않는 과정의 과제를 만들 수 없으며 API를 통해 이를 시도하면 403 PERMISSION_DENIED 오류가 발생합니다.

courses.courseWork.create 메서드를 사용하여 할당을 만들 때 아래 샘플 코드와 같이 링크를 materials로 첨부할 수 있습니다.

자바

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
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 요청에서 할당을 참조하는 데 사용할 수 있는 서버 할당 식별자가 포함됩니다.

클래스룸 API를 통해 만든 과제에 연결된 자료를 포함하려면 리소스 연결을 사용하여 대상 URL을 지정합니다. 클래스룸에서 제목과 썸네일 이미지를 자동으로 가져옵니다. Classroom API는 Google Drive 및 YouTube 자료를 기본적으로 지원하며, DriveFile 리소스 또는 YouTubeVideo 리소스와 유사한 방식으로 포함할 수 있습니다.

기한을 지정하려면 dueDatedueTime 필드를 상응하는 UTC 시간으로 설정합니다. 마감일은 미래 날짜여야 합니다.

과제 및 질문 검색

해당 과정의 학생과 교사 또는 도메인 관리자가 과제와 질문을 검색할 수 있습니다. 특정 과제 또는 질문을 검색하려면 courses.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 리소스를 가져옵니다.

자바

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
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(
          "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 리소스를 검색합니다.

자바

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());
    }
  }

Python

classroom/snippets/classroom_list_student_submissions.py
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(
          "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로 사용합니다.

자바

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

학생 제출물을 검색할 권한이 있다고 해서 첨부파일 또는 첨부파일 메타데이터에 액세스할 수 있는 권한을 의미하지는 않습니다. 실제로는 관리자가 강의 멤버가 아닌 경우 첨부된 Drive 파일의 제목이 표시되지 않을 수 있습니다. 관리자가 사용자 파일에 액세스하도록 허용하려면 도메인 전체 위임 가이드를 참고하세요.

학생 답변에 첨부파일 추가하기

Link, DriveFile 또는 YouTubeVideo 리소스를 첨부하여 학생 제출물에 링크를 첨부할 수 있습니다. 다음 샘플과 같이 courses.courseWork.studentSubmissions.modifyAttachments를 사용하여 이 작업을 실행합니다.

자바

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")

링크 첨부파일은 대상 URL로 정의되며 클래스룸에서 제목과 썸네일 이미지를 자동으로 가져옵니다. 다른 자료에 대한 자세한 내용은 각 참조 페이지에서 확인하실 수 있습니다.

StudentSubmission는 과정 교사 또는 소유한 학생만 수정할 수 있습니다. 학생 제출물의 CourseWorkTypeASSIGNMENT인 경우에만 Materials를 첨부할 수 있습니다.

필요한 범위는 요청하는 사용자가 과정에 있는 역할에 따라 다릅니다. 사용자가 교사인 경우 다음 범위를 사용하세요.

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

사용자가 학생인 경우 다음 범위를 사용하세요.

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