ניהול העבודות והציונים

בממשק המשתמש של Classroom יש תמיכה בחמישה סוגים של עבודות: מטלות, מטלות עם בחנים, שאלות שיש להן תשובות קצרות, שאלות אמריקאיות חומרים. נכון לעכשיו, Classroom API תומך בשלושה מהסוגים האלה, נקראים CourseWorkType דרך ה-API: 'משימות', 'תשובה קצרה' שאלות אמריקאיות ושאלות אמריקאיות.

כדי לגשת לפונקציונליות הזו, אפשר להשתמש מקור המידע על CourseWork, שמייצג מטלה או שאלה שהוקצו לתלמידים לגבי קורס מסוים, כולל חומרי לימוד ופרטים נוספים, כמו תאריך או ציון מקסימלי.

בנוסף למשאב CourseWork, אפשר לנהל מטלות שהושלמו בעזרת המשאב StudentSubmission. הקטעים הבאים מתארים את בצורה מפורטת יותר.

ליצור מטלות.

אפשר ליצור מטלות רק בשם המורים של הקורס ניסיון ליצור מטלות בקורס בשם התלמיד/ה יגרום בשגיאה PERMISSION_DENIED403. באופן דומה, מנהלי דומיינים לא יכולים ליצור בקורסים שהם לא מלמדים ומנסים לעשות זאת דרך ה-API תגרום גם לשגיאה 403 PERMISSION_DENIED.

כשיוצרים מטלות באמצעות השיטה courses.courseWork.create, יכול לצרף קישורים בתור materials, כפי שמוצג בקוד לדוגמה הבא:

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)

התוצאה כוללת מזהה שמוקצה לשרת, שיכול לשמש את ההקצאה בבקשות API אחרות.

כדי לכלול חומרי לימוד מקושרים במטלה שנוצרה באמצעות Classroom API: להשתמש במקור מידע על קישור, את כתובת ה-URL של היעד. המערכת של Classroom מאחזרת באופן אוטומטי את הכותרת ואת התמונה הממוזערת. ה-Classroom API גם תומך במקור ב-Google Drive ובחומרים של YouTube, נכללות במשאב DriveFile או מקור המידע של YouTubeVideo בדרך הזו.

כדי לציין תאריך הגשה, צריך להגדיר את השדות dueDate ו-dueTime המתאים לפי שעון UTC. תאריך היעד חייב להיות בעתיד.

לאחזר מטלות ושאלות

אפשר לאחזר מטלות ושאלות לתלמידים ולמורים הקורס המתאים או מנהל דומיין. כדי לאחזר קוד אימות ספציפי למטלה או לשאלה, נכנסים לקורס classes.courseWork.get. כדי לאחזר את הכול מטלות או שאלות (ניתן להתאים לקריטריונים מסוימים), השתמשו courses.courseWork.list.

ההיקף הנדרש תלוי בתפקיד של המשתמש המבקש כמובן. אם המשתמש הוא תלמיד, תוכלו להשתמש באחד מההיקפים הבאים:

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

אם המשתמש הוא מורה או מנהל דומיין, צריך להשתמש באחת מהאפשרויות הבאות היקפים:

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

קבלת הרשאה לאחזר מטלה או שאלה לא מעידה על כך הרשאות גישה לחומרים או למטא-נתונים של חומרים. בפועל, המשמעות היא שייתכן שאדמין לא יראה את הכותרת של קובץ מצורף ב-Drive, לא משתתפים בקורס. אם רוצים לאפשר לאדמינים גישה למשתמש קבצים, אפשר לעיין במודל ברמת הדומיין מינוי שלוחה הרשאות מותאמת אישית.

ניהול התשובות של התלמידים

StudentSubmission שמייצג את העבודה שבוצעה והציון של תלמיד במטלה או שאלה. StudentSubmission נוצר במרומז לכל תלמיד ותלמידה כששואלים אותם שאלה חדשה המטלה נוצרת.

בקטעים הבאים מוסברות פעולות נפוצות לניהול התשובות של התלמידים.

אחזור תשובות של תלמידים

התלמידים יכולים לאחזר את המטלות שלהם, המורים יכולים לאחזר את המטלות שהם הגישו. לכל הסטודנטים בקורסים שלהם, ומנהלי דומיינים יכולים לאחזר את לכל התלמידים בדומיין שלהם. כל הגשה של תלמיד להקצות מזהה, אם אתם יודעים את המזהה, courses.courseWork.studentSubmissions.get כדי לאחזר אותו.

משתמשים בשיטה courses.courseWork.studentSubmissions.list כדי לקבל StudentSubmission משאבים שתואמים לקריטריונים מסוימים, כמו שאפשר לראות הדוגמה הבאה:

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)

מאחזרים StudentSubmission משאבים ששייכים לתלמיד מסוים באמצעות שמציין את הפרמטר userId, כפי שמוצג בדוגמה הבאה:

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

התלמידים מזוהים לפי המזהה הייחודי או כתובת האימייל של המשתמש, וכן שהוחזר על ידי Google Admin SDK. המשתמש הנוכחי יכול להתייחס גם לרשומות שלו מזהה באמצעות הקיצור "me".

אפשר גם לקבל את ההגשות של התלמידים עבור כל המטלות במסגרת כמובן. כדי לעשות את זה, צריך להשתמש בליטרל "-" בתור courseWorkId, כמו שמוצג הדוגמה הבאה:

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

ההיקף הנדרש תלוי בתפקיד של המשתמש המבקש כמובן. צריך להשתמש בהיקף הבא אם המשתמש הוא מורה או דומיין אדמין:

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

אם המשתמש הוא תלמיד/ה, יש להשתמש בהיקף הבא:

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

קבלת אישור לאחזר את ההגשה של התלמיד או התלמידה לא מעידה על כך הרשאות גישה לקבצים מצורפים או למטא-נתונים של קבצים מצורפים. בפועל, המשמעות היא שאדמין לא יכול לראות את הכותרת של קובץ מצורף ב-Drive, הם לא שייכים לקורס. אם רוצים להעניק הרשאת גישה לאדמינים לקובצי משתמש, עיינו מדריך להענקת גישה ברמת הדומיין.

הוספת קבצים מצורפים לתשובה של התלמידים

אפשר לצרף קישורים להגשת עבודות על ידי צירוף של Link, משאב DriveFile או YouTubeVideo. הפעולה הזו מתבצעת באמצעות courses.courseWork.studentSubmissions.modifyAttachments, כפי שמוצג הדוגמה הבאה:

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

קובץ מצורף של קישור מוגדר על ידי כתובת ה-URL של היעד. מערכת Classroom תפעל באופן אוטומטי אחזור של הכותרת והתמונה הממוזערת. ניתן לקבל מידע על חומרים אחרים בכתובת את דפי העזר המתאימים.

StudentSubmission יכול לשנות רק על ידי מורה של קורס או על ידי התלמיד שהוא הבעלים שלו. אפשר לצרף את Materials רק אם CourseWorkType שהוגשו על ידי התלמיד או התלמידה הם ASSIGNMENT.

ההיקף הנדרש תלוי בתפקיד של המשתמש המבקש כמובן. אם המשתמש הוא מורה, צריך להשתמש בהיקף הבא:

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

אם המשתמש הוא תלמיד/ה, יש להשתמש בהיקף הבא:

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

ניהול מצב התשובות של התלמידים

אפשר לבטל את ההגשה של התשובה של התלמידים, להגיש אותה או להחזיר אותה. שדה המדינה ב-StudentSubmission מציין את המצב הנוכחי. כדי לשנות את המדינה, צריך להתקשר אחת מהשיטות הבאות:

בכל השיטות האלה יש גוף ריק. דוגמה:

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

רק התלמיד שבבעלותו StudentSubmission יכול להגיש את המטלה או להחזיר אותו. אפשר להגיש מחדש רק הגשה שהוגשה. מורים בקורס יכולים להחזיר רק המכשיר StudentSubmission במצב 'הוגשה'.

מתן ציון לתגובות של התלמידים

במשאב StudentSubmission יש שני שדות לשמירת הציונים: assignedGrade, שהוא הציון המדווח לתלמידים, וגם draftGrade, זהו ציון לא סופי שגלוי רק למורים. השדות האלה עודכנו שימוש ב-courses.courseWork.studentSubmissions.patch עם מסכת שדות שמכילים את השדות המתאימים, כפי שמוצג בדוגמה הבאה.

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

כשעובדים עם ממשק המשתמש של Classroom, מורים יכולים לתת ציון רק אחרי שהם שמרו לראשונה טיוטת ציון. לאחר מכן אפשר להחזיר את הציון שהוקצה ל לתלמיד/ה. האפליקציות צריכות לאמולה של ההתנהגות הזו. האפליקציה שלך יכולה לתת ציון למטלה באחת משתי דרכים:

  • הקצאה של draftGrade בלבד. לדוגמה, אפשרות זו שימושית כדי לאפשר למורה לבדוק ידנית את הציונים לפני סיום כולם. התלמידים לא יכולים לראות טיוטות ציונים.

  • כדי לתת ציון מלא למטלה, צריך להקצות גם את draftGrade וגם את assignedGrade.

הצגת רשימת הציונים שהוקצו

כדי להציג את רשימת כל הציונים של פריט מסוים בעבודה, אפשר לעיין אובייקט התגובה של השיטה 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'))}")