Czy Twoi użytkownicy korzystają z Classroom w Google Meet? Zapoznaj się z krótkim przewodnikiem po Apps Script dotyczącym sprawdzania obecności uczniów w kursach Google Meet.

Zarządzanie zadaniami i ocenami

Interfejs Classroom obsługuje 5 typów zadań: Projekty, Projekty quizu, Pytania jednokrotnego wyboru, Pytania jednokrotnego wyboru i Materiały. Interfejs Classroom API obsługuje obecnie 3 typy tych typów. Interfejs API znane jest jako CourseWorkType: Projekty, Pytania z krótką odpowiedzią i Pytania jednokrotnego wyboru.

Aby uzyskać dostęp do tej funkcji, możesz użyć zasobu CourseWork, który reprezentuje projekt lub pytanie przypisane do uczniów w ramach danego kursu, w tym wszelkie dodatkowe materiały i szczegóły, takie jak termin lub maksymalny wynik.

Oprócz zasobu CourseWork możesz zarządzać ukończonymi projektami za pomocą zasobu StudentSubmission. Poniżej znajdziesz więcej szczegółów na ten temat.

Tworzenie projektów

Projekty można utworzyć tylko w imieniu nauczycieli prowadzących zajęcia. Próba utworzenia projektów na zajęciach w imieniu ucznia spowoduje błąd 403 PERMISSION_DENIED. Podobnie administratorzy domen nie mogą tworzyć przypisań w przypadku kursów, których nie uczą, i próbujących tego dokonać przy użyciu interfejsu API również zwracają błąd 403 PERMISSION_DENIED.

Podczas tworzenia przypisań za pomocą metody courses.courseWork.create możesz dołączać linki jako materials, jak pokazano w tym przykładowym kodzie:

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)

Wynik zawiera przypisany przez serwer identyfikator, którego można użyć do odwoływania się do przypisania w innych żądaniach interfejsu API.

Aby dołączyć materiały w projekcie utworzonym przy użyciu interfejsu Classroom API, użyj zasobu linku, który określa docelowy adres URL. Classroom automatycznie pobiera tytuł i miniaturę. Interfejs API Classroom natywnie obsługuje też pliki z Dysku Google i YouTube, które w podobny sposób można uwzględnić w zasobie DyskuFile lub zasobie YouTubeVideo.

Aby określić termin, w polach dueDate i dueTime ustaw odpowiedni czas UTC. Termin musi przypadać w przyszłości.

Pobieranie projektów i pytań

Możesz pobierać projekty i pytania dla uczniów i nauczycieli odpowiadającego im kursu lub przez administratora domeny. Aby znaleźć konkretny projekt lub pytanie, skorzystaj z kursów.courseWork.get. Aby pobrać wszystkie projekty lub pytania (opcjonalnie spełniające określone kryteria), użyj kursucourses.courseWork.list.

Wymagany zakres zależy od roli, którą użytkownik wysyłający żądanie ma w ramach kursu. Jeśli użytkownik jest uczniem, użyj jednego z tych zakresów:

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

Jeśli użytkownik jest nauczycielem lub administratorem domeny, użyj jednego z tych zakresów:

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

Pozwolenie na pobranie projektu lub pytania nie sugeruje uprawnień dostępu do materiałów lub metadanych materiałów. W praktyce oznacza to, że administrator może nie widzieć tytułu załączonego pliku z Dysku, jeśli nie jest uczestnikiem zajęć. Jeśli chcesz zezwolić administratorom na dostęp do plików użytkowników, zapoznaj się z przewodnikiem na temat przekazywania dostępu w całej domenie.

Zarządzanie odpowiedziami uczniów

Zasób StudentSubmission pokazuje wykonane i ocenione zadania ucznia lub danego pytania. Zasób StudentSubmission jest domyślnie tworzony dla każdego ucznia po utworzeniu nowego pytania lub projektu.

W poniższych sekcjach opisano typowe działania, które zarządzają odpowiedziami uczniów.

Pobieranie odpowiedzi uczniów

Uczniowie mogą pobierać własne zadania, nauczyciele mogą pobierać zadania wszystkich uczniów biorących udział w kursach, a administratorzy domen mogą pobierać wszystkie zadania dla wszystkich uczniów w domenie. Każdy projekt przesłany przez tę osobę ma przypisany identyfikator. Jeśli go znasz, możesz go pobrać, korzystając ze identyfikatora courses.courseWork.studentSubmissions.get.

Użyj metody courses.courseWork.studentSubmissions.list, aby uzyskać zasoby StudentSubmission, które spełniają określone kryteria, jak pokazano w tym przykładzie:

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)

Aby pobrać zasoby StudentSubmission należące do określonego ucznia, określ parametr userId, jak w tym przykładzie:

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

Uczniowie są identyfikowani na podstawie unikalnego identyfikatora lub adresu e-mail użytkownika zwróconego przez pakiet Google Admin SDK. Bieżący użytkownik może też odwoływać się do własnego identyfikatora za pomocą skrótu "me".

Możesz też wyświetlić zadania przesłane przez wszystkich uczniów na zajęciach. Aby to zrobić, użyj literału "-" jako courseWorkId, jak w tym przykładzie:

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

Wymagany zakres zależy od roli, którą użytkownik wysyłający żądanie ma w ramach kursu. Jeśli użytkownik jest nauczycielem lub administratorem domeny, użyj tego zakresu:

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

Jeśli użytkownik jest uczniem, użyj tego zakresu:

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

Zezwolenie na pobranie zadania ucznia nie oznacza, że ma on dostęp do załączników lub metadanych załączników. W praktyce oznacza to, że administrator może nie widzieć tytułu załączonego pliku z Dysku, jeśli nie jest uczestnikiem zajęć. Jeśli chcesz zezwolić administratorom na dostęp do plików użytkowników, przeczytaj przewodnik na temat przekazywania dostępu w całej domenie.

Dodawanie załączników do odpowiedzi ucznia

Do materiałów przesłanych przez ucznia możesz dodawać linki, używając zasobu Link, DriveFile lub YouTubeVideo. Można to zrobić w courses.courseWork.studentSubmissions.modifyAttachments, jak w tym przykładzie:

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

zajęcia/fragmenty/klasa_dołączenia.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")

Załącznik linku jest definiowany przez docelowy adres URL. Classroom automatycznie pobiera tytuł i miniaturę. Więcej informacji o pozostałych materiałach znajdziesz na odpowiednich stronach.

StudentSubmission może zostać zmienione tylko przez nauczyciela kursu lub ucznia, który jest jego właścicielem. Możesz dołączyć tylko Materials tylko wtedy, gdy CourseWorkType zadania ucznia to ASSIGNMENT.

Wymagany zakres zależy od roli, którą użytkownik wysyłający żądanie ma w ramach kursu. Jeśli użytkownik jest nauczycielem, użyj tego zakresu:

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

Jeśli użytkownik jest uczniem, użyj tego zakresu:

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

Zarządzanie stanem odpowiedzi uczniów

Odpowiedzi uczniów mogą być nieprzesłane, oddane lub zwrócone. Pole stanu w StudentSubmission wskazuje bieżący stan. Aby zmienić stan, wywołaj jedną z tych metod:

Wszystkie te metody tworzą pustą treść. Przykład:

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

Tylko uczeń, który ma konto StudentSubmission, może je oddać lub odebrać. Można tylko odzyskać oddane zadanie. Nauczyciele biorący udział w zajęciach mogą zwrócić tylko te StudentSubmission, które zostały oddane.

Ocenianie odpowiedzi uczniów

Zasób StudentSubmission zawiera 2 pola do przechowywania ocen: assignedGrade, czyli ocena zgłoszona uczniom, i draftGrade, czyli wstępna ocena widoczna tylko dla nauczycieli. Te pola są aktualizowane za pomocą courses.courseWork.studentSubmissions.patch z maską pola zawierającą odpowiednie pola, jak pokazano w poniższym przykładzie.

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

Podczas pracy z interfejsem Classroom nauczyciele nie mogą przypisywać ocen, dopóki nie zapiszą najpierw wersji roboczej. Następnie przypisana ocena może zostać zwrócona uczniowi. Aplikacje muszą emulować to działanie. Aplikacja może ocenić projekt ucznia na 2 sposoby:

  • Przypisz tylko tag draftGrade. Jest to przydatne na przykład wtedy, gdy chcesz, aby nauczyciel ręcznie sprawdził oceny przed ich ukończeniem. Uczniowie nie widzą ocen roboczych.

  • Aby w pełni ocenić zadanie, przypisz draftGrade i assignedGrade.

Wyświetl listę przypisanych ocen

Aby wyświetlić listę wszystkich ocen związanych z określonym elementem zadania, przejrzyj obiekt odpowiedzi metody courses.courseWork.studentSubmissions.list:

Java

classroom/snippets/src/main/java/ListStudentSubmissions.java
  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 submissions found.");
} else {
  for (StudentSubmission submission : studentSubmissions) {
    System.out.printf(
        "User ID %s, Assigned grade: %s\n",
        submission.getUserId(), submission.getAssignedGrade());
  }
}

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