Administración de trabajos del curso

La app de Classroom admite tres tipos de elementos de transmisión: CourseWork, CourseWorkMaterials y Announcements. En esta guía, se describe cómo administrar CourseWork, pero las APIs de todos los elementos de transmisión son similares. Consulta Recursos de la API para obtener más información sobre los tipos de elementos de transmisión y sus diferencias.

El recurso CourseWork representa un elemento de trabajo que se asignó a los estudiantes de un curso en particular, incluidos los materiales y detalles adicionales, como la fecha de entrega o la puntuación máxima. Hay cuatro subtipos de CourseWork: tareas, tareas con cuestionario, preguntas de respuesta corta y preguntas de opción múltiple. La API de Classroom admite tres de estos subtipos: tareas, preguntas de respuesta corta y preguntas de opción múltiple. Estos tipos se representan con el CourseWork.workType campo.

Además del recurso CourseWork, puedes administrar el trabajo completado con el recurso StudentSubmission.

Crear CourseWork

CourseWork solo se puede crear en nombre del profesor del curso. Si intentas crear CourseWork en nombre de un estudiante o de un administrador de dominio que no es profesor en el curso, se produce un error PERMISSION_DENIED. Consulta Tipos de usuarios para obtener más información sobre los diferentes roles en Classroom.

Cuando creas CourseWork con el método courses.courseWork.create, puedes adjuntar vínculos como materials, como se muestra en el siguiente código de muestra:

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)

Los campos title y workType son obligatorios. Todos los demás campos son opcionales. Si no se especifica state, se crea el CourseWork en estado de borrador.

Usa un recurso Link con un destino especificado url para incluir materiales vinculados en el CourseWork. Classroom recupera automáticamente la title y la URL de la imagen en miniatura (thumbnailUrl). La API de Classroom también admite de forma nativa los materiales de Google Drive y YouTube, que se pueden incluir con un recurso DriveFile o un recurso YouTubeVideo de manera similar.

Para especificar una fecha de entrega, configura los campos dueDate y dueTime en la hora UTC correspondiente. La fecha de entrega debe ser posterior a la fecha actual.

La respuesta CourseWork incluye un identificador asignado por el servidor que se puede usar para hacer referencia a la tarea en otras solicitudes de la API.

Recuperar CourseWork

Puedes recuperar CourseWork en nombre de los estudiantes y profesores del curso correspondiente. También puedes recuperar CourseWork en nombre de los administradores de dominio, incluso si no son profesores en el curso. Para recuperar un específico CourseWork, usa courses.courseWork.get. Para recuperar todos los CourseWork (opcionalmente, que coincidan con algunos criterios), usa courses.courseWork.list.

El alcance requerido depende del rol que tenga el usuario solicitante en el curso. Si el usuario es estudiante, usa uno de los siguientes alcances:

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

Si el usuario es profesor o administrador de dominio, usa uno de los siguientes alcances:

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

Tener permiso para recuperar un CourseWork no implica permisos para acceder a los materiales ni a los metadatos de los materiales. En la práctica, esto significa que un administrador no puede ver el título de un archivo de Drive adjunto si no es miembro del curso.

Administra las respuestas de los estudiantes

Un recurso StudentSubmission representa el trabajo realizado por un estudiante para un CourseWork. El recurso incluye metadatos relacionados con el trabajo, como el estado y la calificación del trabajo. Se crea un StudentSubmission de forma implícita para cada estudiante cuando se crea un CourseWork nuevo.

En las siguientes secciones, se explican las acciones comunes que administran las respuestas de los estudiantes.

Recupera las respuestas de los estudiantes

Los estudiantes pueden recuperar sus propias tareas enviadas, los profesores pueden recuperar las tareas enviadas de todos los estudiantes de sus cursos y los administradores de dominio pueden recuperar todas las tareas enviadas de todos los estudiantes de su dominio. A cada StudentSubmission se le asigna un identificador. Si conoces el identificador, usa courses.courseWork.studentSubmissions.get para recuperar la tarea enviada.

Usa el método courses.courseWork.studentSubmissions.list para obtener todos StudentSubmission recursos que coincidan con algunos criterios, como se muestra en el siguiente ejemplo:

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)

Para recuperar los recursos StudentSubmission que pertenecen a un estudiante en particular, especifica el parámetro userId, como se muestra en el siguiente ejemplo:

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

Los estudiantes se identifican por el ID o la dirección de correo electrónico únicos, como se representa en el Student recurso. El usuario actual también puede hacer referencia a su propio ID con la "me" abreviatura.

También es posible recuperar las tareas enviadas por los estudiantes para todas las tareas de un curso. Para ello, usa el literal "-" como courseWorkId, como se muestra en el siguiente ejemplo:

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

El alcance requerido depende del rol que tenga el usuario solicitante en el curso. Si el usuario es profesor o administrador de dominio, usa el siguiente alcance:

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

Si el usuario es estudiante, usa el siguiente alcance:

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

Tener permiso para recuperar un StudentSubmission no implica permisos para acceder a los archivos adjuntos ni a los metadatos de los archivos adjuntos. En la práctica, esto significa que un administrador no puede ver el título de un archivo de Drive adjunto si no es miembro del curso.

Agrega archivos adjuntos a una respuesta del estudiante

Puedes adjuntar vínculos a una tarea enviada por un estudiante adjuntando un recurso Link, DriveFile o YouTubeVideo. Esto se hace con courses.courseWork.studentSubmissions.modifyAttachments, como se muestra en el siguiente ejemplo:

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

Un archivo adjunto Link se define por el url de destino; Classroom recupera automáticamente la title y la imagen en miniatura (thumbnailUrl). Consulta Material para obtener información sobre los materiales que se pueden adjuntar a StudentSubmissions.

El StudentSubmission solo puede ser modificado por un profesor del curso o por el estudiante que lo posee. Solo puedes adjuntar Materials si el CourseWorkType del StudentSubmission es ASSIGNMENT.

El alcance requerido depende del rol que tenga el usuario solicitante en el curso. Si el usuario es profesor, usa el siguiente alcance:

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

Si el usuario es estudiante, usa el siguiente alcance:

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