Administrar el trabajo de curso

La IU de Classroom admite cinco tipos de trabajo en clase: Tareas, tareas con cuestionario, preguntas de respuesta corta, preguntas de opción múltiple y materiales. Actualmente, la API de Classroom admite tres de estos tipos, que se conocen como CourseWorkType para la API: Tareas, Preguntas de respuesta corta y Preguntas de opción múltiple.

Para acceder a esta función, puedes usar el recurso CourseWork, que representa una tarea o pregunta que se asignó a los estudiantes en un curso en particular, incluidos los materiales y detalles adicionales, como la fecha límite o la puntuación máxima.

Además del recurso CourseWork, puedes administrar las tareas completadas con el recurso StudentSubmission. En las siguientes secciones, se describen estos aspectos con más detalle.

Cómo crear tareas

Las tareas solo se pueden crear en nombre de los profesores del curso. Si intentas crear tareas en un curso en nombre de un estudiante, se mostrará un error PERMISSION_DENIED 403. Del mismo modo, los administradores de dominios tampoco pueden crear tareas para cursos que no imparten, y si intentan hacerlo a través de la API, también se mostrará un error PERMISSION_DENIED 403.

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

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)

El resultado incluye un identificador asignado por el servidor que se puede usar para hacer referencia a la asignación en otras solicitudes a la API.

Para incluir materiales vinculados en una tarea creada con la API de Classroom, usa un recurso de vínculo y especifica la URL de destino. Classroom recupera automáticamente el título y la imagen de la miniatura. 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 límite, establece los campos dueDate y dueTime en la hora UTC correspondiente. La fecha límite debe ser futura.

Cómo recuperar tareas y preguntas

Puedes recuperar tareas y preguntas para estudiantes y profesores del curso correspondiente o un administrador de dominio. Para recuperar una tarea o pregunta específica, usa courses.courseWork.get. Para recuperar todas las tareas o preguntas (de forma opcional, 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 permisos:

  • 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 una tarea o una pregunta no implica permisos para acceder a los materiales ni a sus metadatos. En la práctica, esto significa que es posible que un administrador no vea el título de un archivo adjunto de Drive si no es miembro del curso. Si quieres permitir que los administradores accedan a los archivos del usuario, consulta la guía de delegación en todo el dominio.

Administra las respuestas de los estudiantes

Un recurso StudentSubmission representa el trabajo realizado y la calificación de un estudiante para una tarea o pregunta. Se crea implícitamente un recurso StudentSubmission para cada alumno cuando se crea una pregunta o tarea nueva.

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

Cómo recuperar las respuestas de los estudiantes

Los estudiantes pueden recuperar sus propios envíos, los profesores pueden recuperar los envíos de todos los estudiantes de sus cursos, y los administradores de dominios pueden recuperar todos los envíos de todos los estudiantes de su dominio. A cada entrega del estudiante se le asigna un identificador. Si conoces el identificador, usa courses.courseWork.studentSubmissions.get para recuperarlo.

Usa el método courses.courseWork.studentSubmissions.list para obtener recursos StudentSubmission 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 único o la dirección de correo electrónico del usuario, como lo muestra el SDK de Google Admin. El usuario actual también puede hacer referencia a su propio ID con la abreviatura "me".

También es posible obtener las entregas de los estudiantes de 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. Usa el siguiente permiso si el usuario es profesor o administrador de dominio:

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

Usa el siguiente permiso si el usuario es estudiante:

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

Tener permiso para recuperar el envío de un estudiante no implica permisos para acceder a los archivos adjuntos ni a sus metadatos. En la práctica, esto significa que es posible que un administrador no vea el título de un archivo de Drive adjunto si no es miembro del curso. Si quieres permitir que los administradores accedan a los archivos de los usuarios, consulta la guía de delegación de todo el dominio.

Cómo agregar archivos adjuntos a una respuesta de un estudiante

Para adjuntar vínculos a una entrega de un estudiante, agrega 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")

La URL de destino define un archivo adjunto de vínculo. Classroom recuperará automáticamente el título y la imagen de miniatura. Puedes obtener información sobre los otros materiales en sus respectivas páginas de referencia.

Solo el profesor del curso o el estudiante propietario puede modificar el StudentSubmission. Solo puedes adjuntar Materials si el CourseWorkType del envío del estudiante es ASSIGNMENT.

El alcance requerido depende del rol que tenga el usuario solicitante en el curso. Usa el siguiente permiso si el usuario es profesor:

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

Usa el siguiente permiso si el usuario es estudiante:

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