זהו המדריך הרביעי בסדרת המדריכים בנושא תוספים ל-Classroom.
במדריך הזה תלמדו איך ליצור קבצים מצורפים באמצעות Google Classroom API. אתם מספקים למשתמשים מסלולים לצפייה בתוכן הקובץ המצורף. התצוגות שונות בהתאם לתפקיד של המשתמש בכיתה. המדריך הזה כולל הסבר על קבצים מצורפים מסוג content-type, שלא דורשים הגשה של תלמידים.
במהלך ההסבר המפורט הזה תבצעו את הפעולות הבאות:
- אחזור ושימוש בפרמטרים הבאים של שאילתת התוסף:
-
addOnToken
: אסימון הרשאה שמועבר לתצוגה של איתור קבצים מצורפים. -
itemId
: מזהה ייחודי של מטלת הלימוד, חומר הלימוד או ההודעה שמקבלים את הקובץ המצורף של התוסף. itemType
: הערך יכול להיות courseWork, courseWorkMaterials או announcement.-
courseId
: מזהה ייחודי של הקורס ב-Google Classroom שבו נוצרת המטלה. -
attachmentId
: מזהה ייחודי שמוקצה על ידי Google Classroom לקובץ מצורף של תוסף אחרי שהוא נוצר.
-
- הטמעה של אחסון מתמיד עבור קבצים מצורפים מסוג תוכן.
- לספק נתיבים ליצירת קבצים מצורפים ולהצגת מסגרות iframe של תצוגת המורה ותצוגת התלמיד.
- שולחים את הבקשות הבאות אל Google Classroom Add-ons API:
- יוצרים קובץ מצורף חדש.
- קבלת ההקשר של התוסף, שמזהה אם המשתמש המחובר הוא תלמיד או מורה.
אחרי שמסיימים, אפשר ליצור קבצים מצורפים מסוג תוכן במטלות דרך ממשק המשתמש של Google Classroom כשמחוברים בתור מורה. גם מורים ותלמידים בכיתה יכולים לראות את התוכן.
הפעלת Classroom API
אפשר להתחיל לבצע קריאות ל-Classroom API החל מהשלב הזה. כדי לבצע קריאות ל-API, צריך להפעיל אותו בפרויקט ב-Google Cloud. עוברים אל הערך בספרייה של Google Classroom API ובוחרים באפשרות Enable (הפעלה).
טיפול בפרמטרים של שאילתה בתצוגה של גילוי קבצים מצורפים
כפי שהוסבר קודם, Google Classroom מעביר פרמטרים של שאילתות כשמטעינים את התצוגה של איתור קבצים מצורפים ב-iframe:
-
courseId
: המזהה של הקורס הנוכחי ב-Classroom. -
itemId
: מזהה ייחודי של מטלת הלימוד, חומר הלימוד או ההודעה שמקבלים את הקובץ המצורף של התוסף. itemType
: הערך יכול להיות courseWork, courseWorkMaterials או announcement.-
addOnToken
: אסימון שמשמש לאישור פעולות מסוימות בתוספים של Classroom. -
login_hint
: המזהה ב-Google של המשתמש הנוכחי.
ההסבר המפורט הזה מתייחס ל-courseId
, ל-itemId
, ל-itemType
ול-addOnToken
.
צריך לשמור את הערכים האלה ולהעביר אותם כשמבצעים קריאות ל-Classroom API.
כמו בשלב הקודם של ההסבר המפורט, מאחסנים את הערכים של פרמטר השאילתה שהועבר בסשן. חשוב שנבצע את הפעולה הזו בפעם הראשונה שבה נפתח התצוגה של איתור קבצים מצורפים, כי זו ההזדמנות היחידה של Classroom להעביר את פרמטרי השאילתה האלה.
Python
עוברים לקובץ שרת Flask שמספק נתיבים לתצוגה של איתור קבצים מצורפים (attachment-discovery-routes.py
אם פועלים לפי הדוגמה שסיפקנו). בחלק העליון של נתיב הנחיתה של התוסף
(/classroom-addon
בדוגמה שסיפקנו), מאחזרים ושומרים את פרמטרי השאילתה courseId
, itemId
, itemType
ו-addOnToken
.
# Retrieve the itemId, courseId, and addOnToken query parameters.
if flask.request.args.get("itemId"):
flask.session["itemId"] = flask.request.args.get("itemId")
if flask.request.args.get("itemType"):
flask.session["itemType"] = flask.request.args.get("itemType")
if flask.request.args.get("courseId"):
flask.session["courseId"] = flask.request.args.get("courseId")
if flask.request.args.get("addOnToken"):
flask.session["addOnToken"] = flask.request.args.get("addOnToken")
הערכים האלה ייכתבו לסשן רק אם הם קיימים. הם לא יועברו שוב אם המשתמש יחזור לתצוגת גילוי הקבצים המצורפים מאוחר יותר בלי לסגור את ה-iframe.
הוספת אחסון מתמיד לקבצים מצורפים מסוג תוכן
צריך לשמור עותק מקומי של כל הקבצים המצורפים שנוצרו. כך תוכלו לחפש את התוכן שהמורה בחר באמצעות מזהים שסופקו על ידי Classroom.
מגדירים סכמת מסד נתונים ל-Attachment
. בדוגמה שסיפקנו מוצגים קבצים מצורפים עם תמונה וכיתוב. Attachment
מכיל את המאפיינים הבאים:
-
attachment_id
: מזהה ייחודי של קובץ מצורף. הערך הזה מוקצה על ידי Classroom ומוחזר בתגובה כשיוצרים קובץ מצורף. -
image_filename
: שם הקובץ המקומי של התמונה שרוצים להציג. image_caption
: הכיתוב שיוצג עם התמונה.
Python
מרחיבים את ההטמעה של SQLite ו-flask_sqlalchemy
מהשלבים הקודמים.
עוברים לקובץ שבו הגדרתם את טבלת המשתמשים (models.py
אם אתם פועלים לפי הדוגמה שסיפקנו). מוסיפים את הטקסט הבא בתחתית הקובץ מתחת למחלקה User
.
class Attachment(db.Model):
# The attachmentId is the unique identifier for the attachment.
attachment_id = db.Column(db.String(120), primary_key=True)
# The image filename to store.
image_filename = db.Column(db.String(120))
# The image caption to store.
image_caption = db.Column(db.String(120))
מייבאים את המחלקה החדשה Attachment לקובץ השרת עם נתיבי הטיפול בקבצים המצורפים.
הגדרת מסלולים חדשים
כדי להתחיל את ההדרכה הזו, צריך להגדיר כמה דפים חדשים באפליקציה. התוספים האלה מאפשרים למשתמשים ליצור תוכן ולצפות בו דרך התוסף שלנו.
הוספת מסלולים ליצירת קבצים מצורפים
המורה צריך דפים כדי לבחור תוכן ולשלוח בקשות ליצירת קבצים מצורפים. מטמיעים את הנתיב /attachment-options
כדי להציג למורה אפשרויות לבחירת תוכן. צריך גם תבניות לדפים של בחירת התוכן ואישור היצירה. הדוגמאות שסיפקנו כוללות תבניות לכל אלה, ויכולות גם להציג את הבקשות והתשובות מ-Classroom API.
שימו לב שאפשר גם לשנות את דף הנחיתה הקיים של התצוגה 'איתור קבצים מצורפים' כדי להציג את אפשרויות התוכן, במקום ליצור את הדף החדש /attachment-options
. מומלץ ליצור דף חדש למטרות התרגיל הזה, כדי לשמור על התנהגות ה-SSO שהוטמעה בשלב השני של ההסבר המפורט, כמו ביטול הרשאות האפליקציה. הם אמורים להיות שימושיים לכם כשאתם מפתחים ובודקים את התוסף.
המורה יכול לבחור מתוך קבוצה קטנה של תמונות עם כתוביות בדוגמה שסיפקנו. סיפקנו ארבע תמונות של ציוני דרך מפורסמים, והכתוביות שלהן נגזרות משמות הקבצים.
Python
בדוגמה שסיפקנו, זה נמצא בקובץ webapp/attachment_routes.py
.
@app.route("/attachment-options", methods=["GET", "POST"])
def attachment_options():
"""
Render the attachment options page from the "attachment-options.html"
template.
This page displays a grid of images that the user can select using
checkboxes.
"""
# A list of the filenames in the static/images directory.
image_filenames = os.listdir(os.path.join(app.static_folder, "images"))
# The image_list_form_builder method creates a form that displays a grid
# of images, checkboxes, and captions with a Submit button. All images
# passed in image_filenames will be shown, and the captions will be the
# title-cased filenames.
# The form must be built dynamically due to limitations in WTForms. The
# image_list_form_builder method therefore also returns a list of
# attribute names in the form, which will be used by the HTML template
# to properly render the form.
form, var_names = image_list_form_builder(image_filenames)
# If the form was submitted, validate the input and create the attachments.
if form.validate_on_submit():
# Build a dictionary that maps image filenames to captions.
# There will be one dictionary entry per selected item in the form.
filename_caption_pairs = construct_filename_caption_dictionary_list(
form)
# Check that the user selected at least one image, then proceed to
# make requests to the Classroom API.
if len(filename_caption_pairs) > 0:
return create_attachments(filename_caption_pairs)
else:
return flask.render_template(
"create-attachment.html",
message="You didn't select any images.",
form=form,
var_names=var_names)
return flask.render_template(
"attachment-options.html",
message=("You've reached the attachment options page. "
"Select one or more images and click 'Create Attachment'."),
form=form,
var_names=var_names,
)
כך נוצר הדף 'יצירת קבצים מצורפים' שדומה לדף הבא:
המורה יכול לבחור כמה תמונות. יצירת קובץ מצורף אחד לכל תמונה שהמורה בחר בשיטה create_attachments
.
בקשות ליצירת קובץ מצורף לבעיה
אחרי שאתם יודעים אילו פריטי תוכן המורה רוצה לצרף, אתם שולחים בקשות ל-Classroom API כדי ליצור קבצים מצורפים למטלה שלנו. אחרי שמקבלים תגובה מ-Classroom API, מאחסנים את פרטי הקובץ המצורף במסד הנתונים.
מתחילים בקבלת מופע של שירות Classroom:
Python
בדוגמה שסיפקנו, זה נמצא בקובץ webapp/attachment_routes.py
.
def create_attachments(filename_caption_pairs):
"""
Create attachments and show an acknowledgement page.
Args:
filename_caption_pairs: A dictionary that maps image filenames to
captions.
"""
# Get the Google Classroom service.
classroom_service = googleapiclient.discovery.build(
serviceName="classroom",
version="v1",
credentials=credentials)
שליחת בקשת CREATE
לנקודת הקצה courses.courseWork.addOnAttachments
. לכל תמונה שהמורה בוחר, צריך ליצור קודם אובייקט AddOnAttachment
:
Python
בדוגמה שסיפקנו, זהו המשך של create_attachments
השיטה.
# Create a new attachment for each image that was selected.
attachment_count = 0
for key, value in filename_caption_pairs.items():
attachment_count += 1
# Create a dictionary with values for the AddOnAttachment object fields.
attachment = {
# Specifies the route for a teacher user.
"teacherViewUri": {
"uri":
flask.url_for(
"load_content_attachment", _scheme='https', _external=True),
},
# Specifies the route for a student user.
"studentViewUri": {
"uri":
flask.url_for(
"load_content_attachment", _scheme='https', _external=True)
},
# The title of the attachment.
"title": f"Attachment {attachment_count}",
}
צריך לספק לפחות את השדות teacherViewUri
, studentViewUri
ו-title
לכל קובץ מצורף. teacherViewUri
ו-studentViewUri
מייצגים את כתובות ה-URL שנטענות כשסוג המשתמש הרלוונטי פותח את הקובץ המצורף.
שולחים את אובייקט AddOnAttachment
בגוף הבקשה לנקודת הקצה המתאימה addOnAttachments
. צריך לספק את המזהים courseId
, itemId
, itemType
ו-addOnToken
בכל בקשה.
Python
בדוגמה שסיפקנו, זהו המשך של create_attachments
השיטה.
# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
case "announcements":
parent = classroom_service.courses().announcements()
case "courseWorkMaterials":
parent = classroom_service.courses().courseWorkMaterials()
case _:
parent = classroom_service.courses().courseWork()
# Issue a request to create the attachment.
resp = parent.addOnAttachments().create(
courseId=flask.session["courseId"],
itemId=flask.session["itemId"],
addOnToken=flask.session["addOnToken"],
body=attachment).execute()
יוצרים רשומה לקובץ המצורף הזה במסד הנתונים המקומי כדי שתוכלו לטעון את התוכן הנכון בהמשך. Classroom מחזיר ערך id
ייחודי בתשובה לבקשת היצירה, ולכן צריך להשתמש בו כמפתח הראשי במסד הנתונים. שימו לב גם ש-Classroom מעביר את attachmentId
פרמטר השאילתה כשפותחים את התצוגות למורים ולתלמידים:
Python
בדוגמה שסיפקנו, זהו המשך של create_attachments
השיטה.
# Store the value by id.
new_attachment = Attachment(
# The new attachment's unique ID, returned in the CREATE response.
attachment_id=resp.get("id"),
image_filename=key,
image_caption=value)
db.session.add(new_attachment)
db.session.commit()
בשלב הזה, כדאי להפנות את המשתמש לדף אישור כדי לציין שהוא יצר קבצים מצורפים בהצלחה.
אישור קבצים מצורפים מהתוסף
זה הזמן להוסיף את הכתובות המתאימות לשדה Allowed Attachment URI Prefixes (קידומות URI של קבצים מצורפים מותרים) בדף App Configuration (הגדרת האפליקציה) ב-SDK של Google Workspace Marketplace. התוסף יכול ליצור קבצים מצורפים רק מאחד מקידומות ה-URI שמופיעות בדף הזה. זהו אמצעי אבטחה שמטרתו להקטין את הסיכוי למתקפות מסוג "אדם בתווך".
הגישה הכי פשוטה היא לציין בשדה הזה את הדומיין ברמה העליונה, למשל https://example.com
. https://localhost:<your port number>/
יעבוד אם אתם משתמשים במחשב המקומי כשרת האינטרנט.
הוספת מסלולים לתצוגות של המורה והתלמיד
יש ארבעה iframes שבהם יכול להיות שייטען תוסף של Google Classroom. עד עכשיו יצרת רק מסלולים שמשמשים את ה-iframe של תצוגת גילוי הקבצים המצורפים. לאחר מכן, מוסיפים מסלולים להצגת מסגרות iframe של תצוגת המורה ותצוגת התלמיד.
ה-iframe של תצוגת המורה נדרש כדי להציג תצוגה מקדימה של חוויית התלמיד, אבל אפשר לכלול בו גם מידע נוסף או תכונות עריכה.
תצוגת התלמיד/ה היא הדף שמוצג לכל תלמיד/ה כשהם פותחים קובץ מצורף של תוסף.
לצורך התרגיל הזה, יוצרים נתיב /load-content-attachment
אחד שמציג את התצוגה של המורה ושל התלמיד. משתמשים בשיטות של Classroom API כדי לקבוע אם המשתמש הוא מורה או תלמיד כשהדף נטען.
Python
בדוגמה שסיפקנו, זה נמצא בקובץ webapp/attachment_routes.py
.
@app.route("/load-content-attachment")
def load_content_attachment():
"""
Load the attachment for the user's role."""
# Since this is a landing page for the Teacher and Student View iframes, we
# need to preserve the incoming query parameters.
if flask.request.args.get("itemId"):
flask.session["itemId"] = flask.request.args.get("itemId")
if flask.request.args.get("itemType"):
flask.session["itemType"] = flask.request.args.get("itemType")
if flask.request.args.get("courseId"):
flask.session["courseId"] = flask.request.args.get("courseId")
if flask.request.args.get("attachmentId"):
flask.session["attachmentId"] = flask.request.args.get("attachmentId")
חשוב לזכור שצריך גם לאמת את המשתמש בשלב הזה. כדאי גם לטפל בפרמטר השאילתה login_hint
כאן, ולהפנות את המשתמש לתהליך ההרשאה שלכם אם צריך. מידע נוסף על התהליך הזה זמין בהנחיות מפורטות לכניסה לחשבון שמופיעות במדריכים הקודמים.
לאחר מכן שולחים בקשה לנקודת הקצה getAddOnContext
שתואמת לסוג הפריט.
Python
בדוגמה שסיפקנו, זהו המשך של השיטה load_content_attachment
.
# Create an instance of the Classroom service.
classroom_service = googleapiclient.discovery.build(
serviceName="classroom"
version="v1",
credentials=credentials)
# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
case "announcements":
parent = classroom_service.courses().announcements()
case "courseWorkMaterials":
parent = classroom_service.courses().courseWorkMaterials()
case _:
parent = classroom_service.courses().courseWork()
addon_context_response = parent.getAddOnContext(
courseId=flask.session["courseId"],
itemId=flask.session["itemId"]).execute()
השיטה הזו מחזירה מידע על התפקיד הנוכחי של המשתמש בכיתה.
לשנות את התצוגה שמוצגת למשתמש בהתאם לתפקיד שלו. אחד מהשדות studentContext
או teacherContext
מאוכלס באובייקט התגובה. כדאי לבדוק את הפרטים האלה כדי להבין איך לפנות למשתמש.
בכל מקרה, צריך להשתמש בערך של פרמטר השאילתה attachmentId
כדי לדעת איזה קובץ מצורף לאחזר מהמסד הנתונים שלנו. פרמטר השאילתה הזה מסופק כשפותחים את כתובות ה-URI של תצוגת המורה או תצוגת התלמיד.
Python
בדוגמה שסיפקנו, זהו המשך של השיטה load_content_attachment
.
# Determine which view we are in by testing the returned context type.
user_context = "student" if addon_context_response.get(
"studentContext") else "teacher"
# Look up the attachment in the database.
attachment = Attachment.query.get(flask.session["attachmentId"])
# Set the text for the next page depending on the user's role.
message_str = f"I see that you're a {user_context}! "
message_str += (
f"I've loaded the attachment with ID {attachment.attachment_id}. "
if user_context == "teacher" else
"Please enjoy this image of a famous landmark!")
# Show the content with the customized message text.
return flask.render_template(
"show-content-attachment.html",
message=message_str,
image_filename=attachment.image_filename,
image_caption=attachment.image_caption,
responses=response_strings)
בדיקת התוסף
כדי לבדוק את יצירת הקבצים המצורפים:
- נכנסים אל [Google Classroom] בתור אחד ממשתמשי הבדיקה שלכם עם הרשאת מורה.
- עוברים לכרטיסייה סביבת הלמידה ויוצרים מטלה חדשה.
- לוחצים על הלחצן תוספים מתחת לאזור הטקסט, ואז בוחרים את התוסף הרצוי. ה-iframe נפתח והתוסף טוען את ה-URI של הגדרת הקובץ המצורף שציינתם בדף App Configuration (הגדרת האפליקציה) ב-SDK של Google Workspace Marketplace.
- בוחרים פריט תוכן לצירוף למטלה.
- סוגרים את ה-iframe אחרי שיוצרים את הקובץ המצורף.
בממשק ליצירת מטלות ב-Google Classroom אמור להופיע כרטיס של קובץ מצורף. לוחצים על הכרטיס כדי לפתוח את ה-iframe של תצוגת המורה ומוודאים שהקובץ המצורף הנכון מופיע. לוחצים על הלחצן הקצאה.
כדי לבדוק את חוויית התלמידים:
- לאחר מכן, נכנסים ל-Classroom בתור משתמש בדיקה שהוא תלמיד באותה כיתה שבה משתמש הבדיקה הוא מורה.
- מחפשים את המטלה של המבחן בכרטיסייה 'עבודות'.
- מרחיבים את המטלה ולוחצים על כרטיס הקובץ המצורף כדי לפתוח את ה-iframe של תצוגת התלמיד.
מוודאים שהקובץ המצורף הנכון מופיע אצל התלמיד או התלמידה.
מעולה! הכול מוכן למעבר לשלב הבא: יצירת קבצים מצורפים מסוג פעילות.