Gérer CourseWork

L'application Classroom accepte trois types d'éléments de flux : CourseWork, CourseWorkMaterials et Announcements. Ce guide explique comment gérer CourseWork, mais les API de tous les éléments de flux sont similaires. Pour en savoir plus sur les types d'éléments de flux et leurs différences, consultez les ressources de l'API.

La ressource CourseWork représente un élément de travail qui a été attribué aux élèves d'un cours particulier, y compris les documents et informations supplémentaires, comme la date limite ou le score maximal. Il existe quatre sous-types de CourseWork : les devoirs, les questionnaires, les questions à réponse courte et les questions à choix multiples. L'API Classroom est compatible avec trois de ces sous-types: les devoirs, les questions à réponse courte et les questions à choix multiples. Ces types sont représentés par le champ CourseWork.workType.

En plus de la ressource CourseWork, vous pouvez gérer le travail terminé avec la ressource StudentSubmission.

Créer des travaux et devoirs

Les CourseWork ne peuvent être créées que au nom de l'enseignant du cours. Toute tentative de création de CourseWork au nom d'un élève ou d'un administrateur de domaine qui n'est pas enseignant dans le cours génère une erreur PERMISSION_DENIED. Consultez Types d'utilisateurs pour en savoir plus sur les différents rôles dans Classroom.

Lorsque vous créez un CourseWork à l'aide de la méthode courses.courseWork.create, vous pouvez joindre des liens en tant que materials, comme indiqué dans l'exemple de code ci-dessous:

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

Les champs title et workType sont obligatoires. Tous les autres sont facultatifs. Si state n'est pas spécifié, CourseWork est créé en tant que brouillon.

Utilisez une ressource de lien avec un url cible spécifié pour inclure des éléments associés dans le CourseWork. Classroom extrait automatiquement l'URL title et l'URL de l'image miniature (thumbnailUrl). L'API Classroom est également compatible en mode natif avec les ressources Google Drive et YouTube, qui peuvent être incluses avec une ressource DriveFile ou une ressource YouTubeVideo de manière similaire.

Pour spécifier une date limite, définissez les champs dueDate et dueTime sur l'heure UTC correspondante. La date limite doit se situer dans le futur.

La réponse CourseWork inclut un identifiant attribué par le serveur qui peut être utilisé pour référencer l'attribution dans d'autres requêtes API.

Récupérer CourseWork

Vous pouvez récupérer CourseWork au nom des élèves et des enseignants du cours correspondant. Vous pouvez également récupérer CourseWork au nom des administrateurs de domaine, même s'ils ne sont pas enseignants dans le cours. Pour récupérer un CourseWork spécifique, utilisez courses.courseWork.get. Pour récupérer tous les CourseWork (en respectant éventuellement certains critères), utilisez courses.courseWork.list.

Le champ d'application requis dépend du rôle de l'utilisateur à l'origine de la demande dans le cours. Si l'utilisateur est un élève, utilisez l'un des champs d'application suivants:

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

Si l'utilisateur est un enseignant ou un administrateur de domaine, utilisez l'une des portées suivantes:

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

Le fait d'avoir l'autorisation de récupérer un CourseWork n'implique pas d'autorisations d'accès aux matériaux ni aux métadonnées des matériaux. En pratique, cela signifie qu'un administrateur ne verra peut-être pas le titre d'un fichier Drive joint s'il n'est pas membre du cours.

Gérer les réponses des élèves

Une ressource StudentSubmission représente le travail effectué par un élève pour un CourseWork. La ressource inclut des métadonnées liées au travail, telles que l'état et la note du travail. Un StudentSubmission est créé implicitement pour chaque élève lorsqu'un CourseWork est créé.

Les sections suivantes expliquent les actions courantes permettant de gérer les réponses des élèves.

Récupérer les réponses des élèves

Les élèves peuvent récupérer leurs propres devoirs, les enseignants peuvent récupérer les devoirs de tous les élèves de leurs cours, et les administrateurs de domaine peuvent récupérer tous les devoirs de tous les élèves de leur domaine. Chaque StudentSubmission se voit attribuer un identifiant. Si vous connaissez l'identifiant, utilisez courses.courseWork.studentSubmissions.get pour récupérer l'envoi.

Utilisez la méthode courses.courseWork.studentSubmissions.list pour obtenir toutes les ressources StudentSubmission correspondant à certains critères, comme illustré dans l'exemple suivant:

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

Récupérez les ressources StudentSubmission appartenant à un élève particulier en spécifiant le paramètre userId, comme illustré dans l'exemple suivant:

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

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

Les élèves sont identifiés par leur identifiant unique ou leur adresse e-mail, comme indiqué dans la ressource Student. L'utilisateur actuel peut également faire référence à son propre ID à l'aide de l'abréviation "me".

Vous pouvez également récupérer les devoirs des élèves pour tous les devoirs d'un cours. Pour ce faire, utilisez le littéral "-" comme courseWorkId, comme illustré dans l'exemple suivant:

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

Le champ d'application requis dépend du rôle de l'utilisateur à l'origine de la demande dans le cours. Si l'utilisateur est un enseignant ou un administrateur de domaine, utilisez la portée suivante:

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

Si l'utilisateur est un élève, utilisez le champ d'application suivant:

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

Le fait d'être autorisé à récupérer un StudentSubmission n'implique pas d'autorisations d'accès aux pièces jointes ni aux métadonnées des pièces jointes. En pratique, cela signifie qu'un administrateur ne verra peut-être pas le titre d'un fichier Drive joint s'il n'est pas membre du cours.

Ajouter des pièces jointes à une réponse d'élève

Vous pouvez joindre des liens à un devoir d'élève en joignant une ressource Link, DriveFile ou YouTubeVideo. Pour ce faire, utilisez courses.courseWork.studentSubmissions.modifyAttachments, comme illustré dans l'exemple suivant:

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

Une pièce jointe Link est définie par le url cible. Classroom extrait automatiquement le title et l'image miniature (thumbnailUrl). Consultez Material pour en savoir plus sur les documents pouvant être joints à StudentSubmissions.

Le StudentSubmission ne peut être modifié que par un enseignant du cours ou par l'élève qui en est le propriétaire. Vous ne pouvez associer Materials que si l'CourseWorkType de StudentSubmission est ASSIGNMENT.

Le champ d'application requis dépend du rôle de l'utilisateur à l'origine de la demande dans le cours. Si l'utilisateur est un enseignant, utilisez le champ d'application suivant:

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

Si l'utilisateur est un élève, utilisez le champ d'application suivant:

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