Dies ist die vierte Anleitung in der Reihe zu Classroom-Add-ons.
In dieser Anleitung interagieren Sie mit der Google Classroom API, um Anhänge zu erstellen. Sie stellen Nutzern Routen zum Ansehen des Inhalts des Anhangs zur Verfügung. Die Ansichten unterscheiden sich je nach Rolle des Nutzers in der Klasse. In dieser Anleitung geht es um Anhänge vom Inhaltstyp, für die keine Einreichung durch Schüler oder Studenten erforderlich ist.
In dieser Anleitung führen Sie die folgenden Schritte aus:
- Rufen Sie die folgenden Add-on-Suchparameter ab und verwenden Sie sie:
addOnToken
: Ein Autorisierungstoken, das an die Ansicht „Anhänge – Suche“ übergeben wird.itemId
: Eine eindeutige Kennung für die Kursarbeit, das Kursarbeitsmaterial oder die Mitteilung, an die der Add-on-Anhang gesendet wird.itemType
: Entweder „courseWork“, „courseWorkMaterials“ oder „announcement“.courseId
: Eine eindeutige Kennung für den Google Classroom-Kurs, in dem die Aufgabe erstellt wird.attachmentId
: Eine eindeutige Kennung, die einem Add-on-Anhang nach der Erstellung von Google Classroom zugewiesen wird.
- Implementieren Sie einen nichtflüchtigen Speicher für Anhänge mit Inhaltstypen.
- Geben Sie Routen an, um Anhänge zu erstellen und die Iframes für die Ansicht der Lehrkraft und die Ansicht der Schüler/Studenten zu senden.
- Senden Sie die folgenden Anfragen an die Google Classroom Add-ons API:
- Erstellen Sie einen neuen Anhang.
- Rufen Sie den Add-on-Kontext ab, der angibt, ob der angemeldete Nutzer ein Schüler/Student oder eine Lehrkraft ist.
Wenn Sie fertig sind, können Sie über die Google Classroom-Benutzeroberfläche, wenn Sie als Lehrkraft angemeldet sind, Inhaltstyp-Anhänge zu Aufgaben erstellen. Lehrkräfte und Schüler/Studenten können sich die Inhalte ebenfalls ansehen.
Classroom API aktivieren
Rufen Sie ab diesem Schritt die Classroom API auf. Die API muss für Ihr Google Cloud-Projekt aktiviert sein, bevor Sie sie aufrufen können. Gehen Sie zum Bibliothekseintrag der Google Classroom API und wählen Sie Aktivieren aus.
Umgang mit den Suchparametern der Ansicht „Anhänge – Suche“
Wie bereits erwähnt, übergibt Google Classroom Abfrageparameter beim Laden der Ansicht „Anhängesuche“ im IFrame:
courseId
: Die ID des aktuellen Classroom-Kurses.itemId
: Eine eindeutige Kennung für die Kursarbeit, das Kursarbeitsmaterial oder die Mitteilung, an die der Add-on-Anhang gesendet wird.itemType
: Entweder „courseWork“, „courseWorkMaterials“ oder „announcement“.addOnToken
: Ein Token, mit dem bestimmte Aktionen von Classroom-Add-ons autorisiert werden.login_hint
: Die Google-ID des aktuellen Nutzers.
Diese Schritt-für-Schritt-Anleitung richtet sich an courseId
, itemId
, itemType
und addOnToken
.
Behalten Sie diese bei und geben Sie sie beim Aufrufen der Classroom API weiter.
Speichern Sie wie im vorherigen Schritt-für-Schritt-Schritt die übergebenen Abfrageparameterwerte in unserer Sitzung. Das ist wichtig, wenn die Ansicht „Anhänge – Suche“ zum ersten Mal geöffnet wird, da dies die einzige Möglichkeit ist, dass Classroom diese Abfrageparameter übergeben kann.
Python
Rufen Sie die Flask-Serverdatei auf, die Routen für die Discovery-Ansicht für Anhänge enthält (attachment-discovery-routes.py
, wenn Sie unserem Beispiel folgen). Rufen Sie oben in der Landingpage-Route des Add-ons (/classroom-addon
in unserem Beispiel) die Abfrageparameter courseId
, itemId
, itemType
und addOnToken
ab und speichern Sie sie.
# 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")
Diese Werte werden nur in die Sitzung geschrieben, wenn sie vorhanden sind. Sie werden nicht noch einmal übergeben, wenn der Nutzer später zur Ansicht zur Suche nach Anhängen zurückkehrt, ohne den Iframe zu schließen.
Nichtflüchtigen Speicher für Anhänge mit Inhaltstyp hinzufügen
Sie benötigen einen lokalen Eintrag aller erstellten Anhänge. So können Sie die Inhalte, die die Lehrkraft ausgewählt hat, anhand der von Classroom bereitgestellten IDs aufrufen.
Richten Sie ein Datenbankschema für ein Attachment
ein. In unserem Beispiel sind Anhänge mit einem Bild und einer Bildunterschrift zu sehen. Ein Attachment
enthält die folgenden Attribute:
attachment_id
: Eine eindeutige Kennung für einen Anhang. Von Classroom zugewiesen und in der Antwort beim Erstellen eines Anhangs zurückgegeben.image_filename
: Der lokale Dateiname des Bildes, das angezeigt werden soll.image_caption
: Die Bildunterschrift, die mit dem Bild angezeigt werden soll.
Python
Erweitern Sie die SQLite- und flask_sqlalchemy
-Implementierung aus den vorherigen Schritten.
Rufen Sie die Datei auf, in der Sie die Tabelle „Nutzer“ definiert haben (models.py
, wenn Sie unserem Beispiel folgen). Fügen Sie die folgenden Zeilen unten in der Datei unter der Klasse User
hinzu.
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))
Importieren Sie die neue Anhangsklasse mit Ihren Anhangs-Routing-Pfaden in die Serverdatei.
Neue Routen einrichten
Beginnen Sie diesen Schritt, indem Sie einige neue Seiten in unserer Anwendung einrichten. Mit diesen können Nutzer Inhalte über unser Add-on erstellen und ansehen.
Routen zur Anhangerstellung hinzufügen
Sie benötigen Seiten, auf denen die Lehrkraft Inhalte auswählen und Anfragen zum Erstellen von Anhängen ausstellen kann. Implementieren Sie die Route /attachment-options
, um Inhaltsoptionen für die Auswahl durch die Lehrkraft anzuzeigen. Außerdem benötigen Sie Vorlagen für die Seiten zur Inhaltsauswahl und zur Bestätigung der Erstellung. Unsere bereitgestellten Beispiele enthalten Vorlagen dafür. Außerdem können darin die Anfragen und Antworten der Classroom API angezeigt werden.
Sie können auch die Landingpage Ihrer vorhandenen Ansicht für die Suche nach Anhängen ändern, um die Inhaltsoptionen anzuzeigen, anstatt die neue Seite /attachment-options
zu erstellen. Wir empfehlen, für diese Übung eine neue Seite zu erstellen, damit das im zweiten Schritt implementierte SSO-Verhalten erhalten bleibt, z. B. der Widerruf der App-Berechtigungen. Diese sollten sich beim Erstellen und Testen Ihres Add-ons als nützlich erweisen.
Eine Lehrkraft kann in unserem Beispiel aus einer kleinen Gruppe von Bildern mit Untertiteln auswählen. Wir haben vier Bilder berühmter Wahrzeichen bereitgestellt, deren Bildunterschriften aus den Dateinamen abgeleitet sind.
Python
In unserem Beispiel befindet sich dies in der Datei 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,
)
Daraufhin wird die Seite „Anhänge erstellen“ angezeigt, die in etwa so aussieht:
Die Lehrkraft kann mehrere Bilder auswählen. Erstellen Sie einen Anhang für jedes Bild, das die Lehrkraft mit der Methode create_attachments
ausgewählt hat.
Anfragen zum Erstellen von Anhängen senden
Nachdem Sie nun wissen, welche Inhalte die Lehrkraft anhängen möchte, können Sie Anfragen an die Classroom API senden, um Anhänge zu unserer Aufgabe zu erstellen. Speichern Sie die Details des Anhangs in Ihrer Datenbank, nachdem Sie eine Antwort von der Classroom API erhalten haben.
Rufen Sie zuerst eine Instanz des Classroom-Dienstes ab:
Python
In unserem Beispiel befindet sich diese in der Datei 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)
Stelle eine CREATE
-Anfrage an den Endpunkt courses.courseWork.addOnAttachments
. Erstellen Sie für jedes vom Lehrer ausgewählte Bild zuerst ein AddOnAttachment
-Objekt:
Python
In unserem Beispiel ist dies eine Fortsetzung der Methode 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}",
}
Für jeden Anhang müssen mindestens die Felder teacherViewUri
, studentViewUri
und title
angegeben werden. teacherViewUri
und studentViewUri
stellen die URLs dar, die geladen werden, wenn der Anhang durch den jeweiligen Nutzertyp geöffnet wird.
Senden Sie das AddOnAttachment
-Objekt im Anfragetext an den entsprechenden addOnAttachments
-Endpunkt. Geben Sie bei jeder Anfrage die Kennungen courseId
, itemId
, itemType
und addOnToken
an.
Python
In unserem Beispiel ist dies eine Fortsetzung der Methode 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()
Erstellen Sie einen Eintrag für diesen Anhang in Ihrer lokalen Datenbank, damit Sie später den richtigen Inhalt laden können. Classroom gibt in der Antwort auf die Erstellungsanfrage einen eindeutigen id
-Wert zurück. Verwenden Sie diesen als Primärschlüssel in unserer Datenbank. Beachten Sie außerdem, dass Classroom beim Öffnen der Ansicht für Lehrkräfte und Schüler/Studenten den Abfrageparameter attachmentId
übergibt:
Python
In unserem Beispiel ist dies eine Fortsetzung der Methode 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()
Erwägen Sie, den Nutzer an dieser Stelle auf eine Bestätigungsseite weiterzuleiten und zu bestätigen, dass er Anhänge erstellt hat.
Anhänge aus Ihrem Add-on zulassen
Fügen Sie jetzt auf der Seite App-Konfiguration des Google Workspace Marketplace SDK im Feld „Zulässige URI-Präfixe für Anhänge“ alle entsprechenden Adressen hinzu. Ihr Add-on kann nur Anhänge mit einem der auf dieser Seite aufgeführten URI-Präfixe erstellen. Dies ist eine Sicherheitsmaßnahme, die das Risiko von Man-in-the-Middle-Angriffen verringert.
Am einfachsten geben Sie in diesem Feld Ihre Top-Level-Domain an, z. B. https://example.com
. https://localhost:<your port number>/
würde funktionieren, wenn Sie Ihren lokalen Computer als Webserver verwenden.
Routen für die Ansichten „Lehrkraft“ und „Schüler/Student“ hinzufügen
Es gibt vier iFrames, in denen ein Google Classroom-Add-on geladen werden kann. Sie haben bisher nur Routen erstellt, über die der iFrame für die Ansicht „Anhang – Entdecken“ ausgeliefert wird. Fügen Sie als Nächstes Routen hinzu, um auch die Iframes für die Ansichten von Lehrkräften und Schülern zu senden.
Der iFrame Teacher View ist erforderlich, um eine Vorschau der Aktivitäten für Schüler und Studenten anzuzeigen. Optional kann er aber zusätzliche Informationen oder Bearbeitungsfunktionen enthalten.
Die Schüleransicht ist die Seite, die jedem Schüler angezeigt wird, wenn er einen Add-on-Anhang öffnet.
Erstellen Sie für diese Übung eine einzelne /load-content-attachment
-Route, die sowohl die Ansicht für Lehrkräfte als auch die Ansicht für Schüler/Studenten anzeigt. Mithilfe von Classroom API-Methoden können Sie beim Laden der Seite ermitteln, ob der Nutzer eine Lehrkraft oder ein Schüler/Student ist.
Python
In unserem Beispiel befindet sich dies in der Datei 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")
Denken Sie daran, dass Sie den Nutzer an dieser Stelle auch authentifizieren sollten. Hier solltest du auch den Abfrageparameter login_hint
verarbeiten und den Nutzer bei Bedarf zu deinem Autorisierungsvorgang weiterleiten. Weitere Informationen zu diesem Ablauf finden Sie in den Details zur Anmeldung, die in den vorherigen Schritt-für-Schritt-Anleitungen erläutert wurden.
Senden Sie dann eine Anfrage an den Endpunkt getAddOnContext
, die dem Elementtyp entspricht.
Python
In unserem Beispiel ist dies eine Fortsetzung der Methode 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()
Diese Methode gibt Informationen zur Rolle des aktuellen Nutzers in der Klasse zurück.
Die Ansicht, die dem Nutzer angezeigt wird, kann je nach Rolle geändert werden. Im Antwortobjekt muss genau eines der Felder studentContext
oder teacherContext
ausgefüllt sein. Anhand dieser Informationen können Sie entscheiden, wie Sie den Nutzer ansprechen.
Anhand des Werts des Abfrageparameters attachmentId
können Sie in jedem Fall ermitteln, welcher Anhang aus unserer Datenbank abgerufen werden soll. Dieser Abfrageparameter wird beim Öffnen der URIs für die Ansicht der Lehrkraft oder der Schüler/Studenten angegeben.
Python
In unserem Beispiel ist dies eine Fortsetzung der Methode 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)
Add-on testen
Führen Sie die folgenden Schritte aus, um das Erstellen von Anhängen zu testen:
- Melden Sie sich in [Google Classroom] als einer Ihrer Lehrkraft-Testnutzer an.
- Gehen Sie zum Tab Kursaufgaben und erstellen Sie eine neue Aufgabe.
- Klicken Sie unter dem Textfeld auf die Schaltfläche Add-ons und wählen Sie das gewünschte Add-on aus. Der Iframe wird geöffnet und das Add-on lädt den URI für die Einrichtung von Anhängen, den Sie auf der Seite App-Konfiguration des Google Workspace Marketplace SDK angegeben haben.
- Wählen Sie einen Inhalt aus, den Sie der Aufgabe anhängen möchten.
- Schließen Sie den IFrame, nachdem der Vorgang zum Erstellen des Anhangs abgeschlossen ist.
In der Benutzeroberfläche zum Erstellen von Aufgaben in Google Classroom sollte eine Anhängekarte angezeigt werden. Klicken Sie auf die Karte, um den iFrame der Lehrkraft-Ansicht zu öffnen, und prüfen Sie, ob der richtige Anhang angezeigt wird. Klicken Sie auf die Schaltfläche Zuweisen.
So testen Sie die Funktionen für Schüler/Studenten:
- Melden Sie sich dann als Schüler-/Studenten-Testnutzer in Classroom in demselben Kurs an wie der Lehrkraft-Testnutzer.
- Suchen Sie auf dem Tab „Kursaufgaben“ nach der Testaufgabe.
- Maximieren Sie die Aufgabe und klicken Sie auf die Karte „Anhang“, um den IFrame für die Schüler-/Studentenansicht zu öffnen.
Prüfen Sie, ob der richtige Anhang für den Schüler/Studenten angezeigt wird.
Glückwunsch! Sie können mit dem nächsten Schritt fortfahren: Anhänge vom Typ „Aktivität“ erstellen.