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

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Interfejs Classroom obsługuje 5 typów zadań: Projekty, Projekty quizu, Pytania jednokrotnego wyboru, Pytania jednokrotnego wyboru i Materiały. Interfejs API Classroom obsługuje obecnie 3 z tych typów: CourseWorkType (Projekty): pytania w Projektach, 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 przydzielone uczniom na określonych zajęciach, w tym wszelkie dodatkowe materiały i informacje, takie jak termin lub maksymalny wynik.

Oprócz zasobu CourseWork możesz zarządzać ukończonymi projektami za pomocą zasobu StudentSubmission. Szczegółowo opisujemy to w kolejnych sekcjach.

Tworzenie projektów

Projekty można utworzyć tylko w imieniu nauczycieli zajęć, a próba utworzenia projektów w ich imieniu spowoduje błąd 403 PERMISSION_DENIED. Podobnie administratorzy domeny nie mogą także przypisywać projektów w przypadku zajęć, których nie uczą, a próbujące tego zrobić przy użyciu interfejsu API również zwracają błąd 403 PERMISSION_DENIED.

Podczas tworzenia projektów za pomocą metody courses.courseWork.create możesz dołączać linki jako materials, tak jak w przykładowym kodzie poniżej:

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/snippet/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 do interfejsu API.

Aby dołączyć do projektu linki do materiałów utworzonych w interfejsie Classroom API, użyj zasobu linku, który określa docelowy adres URL. Classroom automatycznie pobiera tytuł i miniaturę. Interfejs Classroom API natywnie obsługuje też Dysk Google i materiały w YouTube, które w podobny sposób można dodać do zasobu DriveFile lub 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 danego kursu lub administratora domeny. Aby znaleźć konkretny projekt lub pytanie, użyj kursów.coursework.get. Aby pobrać wszystkie projekty lub pytania (opcjonalnie odpowiadające określonym kryteriom), użyj kursucourse.courseWork.list.

Wymagany zakres zależy od roli, jaką użytkownik w tym kursie ma w swoim kursie. 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

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

Zarządzanie odpowiedziami uczniów

Zasób StudentSubmission reprezentuje zadanie ucznia i ocenę za jego zadanie lub pytanie. Po utworzeniu nowego pytania lub projektu dla każdego ucznia jest domyślnie tworzony zasób StudentSubmission.

W kolejnych sekcjach opisujemy częste działania służące do zarządzania odpowiedziami uczniów.

Pobieranie odpowiedzi uczniów

Uczniowie mogą pobierać swoje prace, nauczyciele mogą pobierać zadania wszystkich uczniów ze swoich zajęć, a administratorzy domeny mogą pobierać wszystkie zadania ze wszystkich swoich uczniów. Do każdego zadania ucznia jest przypisywany identyfikator. Jeśli znasz identyfikator, pobierz go za pomocą narzędzia courses.courseWork.studentSubmissions.get.

Użyj metody courses.courseWork.studentSubmissions.list, aby pobrać 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/snippet/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 zgodnie z tym przykładem:

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());
    }
  }
} 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 userId (%s) does " + "not exist.\n",
        courseId, courseWorkId, userId);
  } else {
    throw e;
  }
} catch (Exception e) {
  throw e;
}
return studentSubmissions;

Python

classroom/snippet/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 mogą poznać unikalny identyfikator lub adres e-mail użytkownika, korzystając z pakietu SDK Google Admin. Bieżący użytkownik może również odwoływać się do swojego identyfikatora za pomocą skrótu "me".

Możesz też pobrać zadania uczniów ze wszystkich projektów w ramach tego kursu. 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, jaką użytkownik w tym kursie ma w swoim kursie. Użyj tego zakresu, jeśli użytkownik jest nauczycielem lub administratorem domeny:

  • 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

Uprawnienia do pobierania zadań uczniów nie oznaczają, że mają one 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 członkiem zajęć. Jeśli chcesz zezwolić administratorom na dostęp do plików użytkowników, zapoznaj się z przewodnikiem po przekazywaniu dostępu w całej domenie.

Dodawanie załączników do odpowiedzi ucznia

Możesz też dodawać linki do zadań uczniów za pomocą zasobu Link, DriveFile lub YouTubeVideo. Możesz to zrobić w courses.courseWork.studentSubmissions.modifyAttachments, tak jak w tym przykładzie:

Java

classroom/snippets/src/main/java/ModifiedAttachmentsStudentSubmission.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/fragments/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")

Załącznik jest określany przez docelowy adres URL; Classroom automatycznie pobiera tytuł i miniaturę. Pozostałe materiały można znaleźć na odpowiednich stronach referencyjnych.

StudentSubmission może modyfikować tylko nauczyciel prowadzący zajęcia lub uczeń, który jest właścicielem. Możesz dołączyć Materials tylko wtedy, gdy CourseWorkType zadania przesłanego przez ucznia to ASSIGNMENT.

Wymagany zakres zależy od roli, jaką użytkownik w tym kursie ma w swoim kursie. Użyj tego zakresu, jeśli użytkownik jest nauczycielem:

  • 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 ucznia

Odpowiedź ucznia może zostać wycofana, oddana lub zwrócona. Pole stanu w StudentSubmission wskazuje bieżący stan. Aby zmienić stan, wywołaj jedną z tych metod:

Wszystkie te metody wymagają pustej treści. 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 jest właścicielem konta StudentSubmission, może je oddać lub odzyskać. Możesz tylko wykorzystać oddane zadanie. Nauczyciele kursów mogą zwracać tylko StudentSubmission w stanie oddanych.

Ocenianie odpowiedzi uczniów

Zasób StudentSubmission zawiera 2 pola do przechowywania ocen: assignedGrade – ocena zgłoszona uczniom i draftGrade – ocena wstępna 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 w interfejsie Classroom nauczyciele nie mogą przypisywać ocen, dopóki nie zapiszą oceny roboczej. Przypisana ocena może zostać zwrócona uczniowi. Aplikacje muszą emulować to zachowanie. Aplikacja może oceniać projekty uczniów na 2 sposoby:

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

  • Przypisz wartości draftGrade i assignedGrade, aby w pełni ocenić zadanie.

Wyświetl listę przypisanych ocen

Możesz wyświetlić wszystkie oceny dla konkretnego elementu zadania, przeglądając obiekt odpowiedzi metody courses.courseWork.studentSubmissions.list:

Java

ListStudentSubmissionsResponse response = service.courses().courseWork().studentSubmissions()
    .list(courseId, courseWorkId)
    .execute();

if (response.getStudentSubmissions() != null) {
  List<StudentSubmission> submissionList = response.getStudentSubmissions();

  for (StudentSubmission submission : submissionList) {
    System.out.printf("User ID %s, Assigned grade: %s", submission.getUserId(),
        submission.getAssignedGrade());
  }
} else {
  System.out.println("No submissions found.");
}

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