To czwarta instrukcja z serii instrukcji dotyczących dodatków do Classroom.
W tym samouczku będziesz wchodzić w interakcję z interfejsem Google Classroom API, aby tworzyć załączniki. Udostępniasz użytkownikom trasy, które umożliwiają wyświetlanie treści załącznika. Widoki różnią się w zależności od roli użytkownika w zajęciach. Ten przewodnik obejmuje załączniki typu treść, które nie wymagają przesłania przez ucznia.
W ramach tego przewodnika wykonasz te czynności:
- Pobierz i użyj tych dodatkowych parametrów zapytania:
addOnToken
: token autoryzacji przekazany do widoku wykrywania załączników.itemId
: unikalny identyfikator elementu CourseWork, CourseWorkMaterial lub Announcement, do którego dodawany jest załącznik dodatku.itemType
: „courseWork”, „courseWorkMaterials” lub „announcement”.courseId
: Unikalny identyfikator kursu w Google Classroom, w którym tworzone jest zadanie.attachmentId
: unikalny identyfikator przypisany przez Google Classroom do załącznika dodatku po jego utworzeniu.
- Wdróż trwałą pamięć masową dla załączników typu content-type.
- Udostępniaj trasy do tworzenia załączników oraz do wyświetlania ramek iframe Widok nauczyciela i Widok ucznia.
- Wydaj te żądania do interfejsu Google Classroom Add-ons API:
- Utwórz nowy załącznik.
- Pobierz kontekst dodatku, który określa, czy zalogowany użytkownik jest uczniem czy nauczycielem.
Po zakończeniu tego procesu możesz tworzyć załączniki typu treść w projektach w interfejsie Google Classroom po zalogowaniu się jako nauczyciel. Nauczyciele i uczniowie w klasie również mogą wyświetlać treści.
Włączanie interfejsu Classroom API
Zacznij wywoływać interfejs API Classroom od tego kroku. Aby można było wywoływać interfejs API, musi on być włączony w Twoim projekcie Google Cloud. Otwórz bibliotekę interfejsu Google Classroom API i kliknij Włącz.
Obsługa parametrów zapytania widoku wykrywania załączników
Jak wcześniej wspomnieliśmy, Google Classroom przekazuje parametry zapytania podczas wczytywania widoku wykrywania załączników w elemencie iframe:
courseId
: identyfikator bieżącego kursu w Classroom.itemId
: unikalny identyfikator elementu CourseWork, CourseWorkMaterial lub Announcement, do którego dodawany jest załącznik dodatku.itemType
: „courseWork”, „courseWorkMaterials” lub „announcement”.addOnToken
: token używany do autoryzacji niektórych działań dodatku do Classroom.login_hint
: identyfikator Google bieżącego użytkownika.
Ten przewodnik obejmuje courseId
, itemId
, itemType
i addOnToken
.
Zachowaj te wartości i przekazuj je podczas wywoływania interfejsu Classroom API.
Podobnie jak w poprzednim kroku, zapisz przekazane wartości parametrów zapytania w sesji. Jest to ważne, ponieważ musimy to zrobić przy pierwszym otwarciu widoku wykrywania załączników. To jedyna okazja, aby Classroom przekazał te parametry zapytania.
Python
Otwórz plik serwera Flask, który udostępnia trasy dla widoku wykrywania załączników (attachment-discovery-routes.py
jeśli korzystasz z naszego przykładu). U góry trasy strony docelowej dodatku (/classroom-addon
w podanym przez nas przykładzie) pobierz i zapisz parametry zapytania courseId
, itemId
, itemType
i 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")
Zapisuj te wartości w sesji tylko wtedy, gdy są obecne. Nie są one ponownie przekazywane, jeśli użytkownik wróci później do widoku wykrywania załączników bez zamykania elementu iframe.
Dodawanie trwałego miejsca na dane do załączników typu treści
Musisz mieć lokalny rekord utworzonych załączników. Umożliwia to wyszukiwanie treści wybranych przez nauczyciela za pomocą identyfikatorów podanych przez Classroom.
Skonfiguruj schemat bazy danych dla Attachment
. Podany przez nas przykład zawiera załączniki z obrazem i podpisem. Attachment
zawiera te atrybuty:
attachment_id
: unikalny identyfikator załącznika. Przypisany przez Classroom i zwracany w odpowiedzi podczas tworzenia załącznika.image_filename
: lokalna nazwa pliku obrazu do wyświetlenia.image_caption
: Podpis, który ma być wyświetlany z obrazem.
Python
Rozszerz implementację SQLite i flask_sqlalchemy
z poprzednich kroków.
Otwórz plik, w którym zdefiniowano tabelę użytkowników (models.py
jeśli korzystasz z naszego przykładu). Na końcu pliku, pod klasą User
, dodaj te wiersze:
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))
Zaimportuj nową klasę Attachment do pliku serwera z trasami obsługi załączników.
Konfigurowanie nowych tras
Zacznij od skonfigurowania nowych stron w aplikacji. Umożliwiają one użytkownikowi tworzenie i wyświetlanie treści za pomocą naszego dodatku.
Dodawanie tras tworzenia załączników
Potrzebujesz stron, na których nauczyciel może wybierać treści i przesyłać prośby o utworzenie załączników. Zaimplementuj trasę /attachment-options
, aby wyświetlić opcje treści, które nauczyciel może wybrać. Potrzebujesz też szablonów stron wyboru treści i potwierdzenia utworzenia. Podane przez nas przykłady zawierają szablony tych elementów, a także mogą wyświetlać żądania i odpowiedzi z interfejsu Classroom API.
Zamiast tworzyć nową stronę /attachment-options
, możesz zmodyfikować dotychczasową stronę docelową widoku wykrywania załączników, aby wyświetlała opcje treści. Zalecamy utworzenie nowej strony na potrzeby tego ćwiczenia, aby zachować działanie logowania jednokrotnego zaimplementowane w drugim kroku przewodnika, np. odwoływanie uprawnień aplikacji. Powinny one okazać się przydatne podczas tworzenia i testowania dodatku.
Nauczyciel może wybrać jeden z niewielkiego zestawu obrazów z napisami w naszym przykładzie. Przygotowaliśmy 4 zdjęcia znanych miejsc, których podpisy pochodzą z nazw plików.
Python
W naszym przykładzie jest to plik 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,
)
Spowoduje to wyświetlenie strony „Utwórz załączniki” podobnej do tej:
Nauczyciel może wybrać kilka obrazów. Utwórz 1 załącznik dla każdego obrazu wybranego przez nauczyciela w create_attachments
.
Żądania utworzenia załącznika do zgłoszenia
Teraz, gdy wiesz, które treści nauczyciel chce dołączyć, wyślij żądania do interfejsu Classroom API, aby utworzyć załączniki do zadania. Po otrzymaniu odpowiedzi z interfejsu Classroom API zapisz szczegóły załącznika w bazie danych.
Zacznij od uzyskania instancji usługi Classroom:
Python
W naszym przykładzie jest to plik 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)
Wyślij żądanie CREATE
do punktu końcowego courses.courseWork.addOnAttachments
. Dla każdego obrazu wybranego przez nauczyciela najpierw utwórz AddOnAttachment
obiekt:
Python
W podanym przykładzie jest to kontynuacja create_attachments
metody.
# 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}",
}
W przypadku każdego załącznika musisz podać co najmniej pola teacherViewUri
, studentViewUri
i title
. Symbole teacherViewUri
i studentViewUri
reprezentują adresy URL, które są wczytywane, gdy załącznik jest otwierany przez
odpowiedni typ użytkownika.
Wyślij obiekt AddOnAttachment
w treści żądania do odpowiedniego punktu końcowego addOnAttachments
. W każdym żądaniu podaj identyfikatory courseId
, itemId
, itemType
i addOnToken
.
Python
W podanym przykładzie jest to kontynuacja create_attachments
metody.
# 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()
Utwórz wpis dla tego załącznika w lokalnej bazie danych, aby później móc wczytać odpowiednią treść. Classroom zwraca w odpowiedzi na żądanie utworzenia unikalną wartość id
, więc użyj jej jako klucza podstawowego w naszej bazie danych. Pamiętaj też, że Classroom przekazuje parametr zapytania attachmentId
podczas otwierania widoków nauczyciela i ucznia:
Python
W podanym przykładzie jest to kontynuacja create_attachments
metody.
# 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()
W tym momencie możesz przekierować użytkownika na stronę potwierdzenia, aby poinformować go, że załączniki zostały utworzone.
Zezwalanie na załączniki z dodatku
Teraz jest dobry moment, aby dodać odpowiednie adresy do pola Dozwolone prefiksy URI załączników na stronie Konfiguracja aplikacji w pakiecie SDK Google Workspace Marketplace. Dodatek może tworzyć załączniki tylko z jednego z prefiksów URI wymienionych na tej stronie. Jest to środek bezpieczeństwa, który pomaga zmniejszyć ryzyko ataków typu „man in the middle”.
Najprostszym rozwiązaniem jest podanie w tym polu domeny najwyższego poziomu, np. https://example.com
. https://localhost:<your port number>/
zadziała, jeśli używasz komputera lokalnego jako serwera WWW.
Dodawanie tras do widoków nauczyciela i ucznia
Istnieją 4 ramki iframe, w których można wczytać dodatek do Google Classroom. Do tej pory utworzono tylko trasy, które obsługują element iframe widoku wykrywania załączników. Następnie dodaj trasy, aby obsługiwać też ramki iframe widoku nauczyciela i ucznia.
Ramka iframe Widok nauczyciela jest wymagana do wyświetlania podglądu środowiska ucznia, ale opcjonalnie może zawierać dodatkowe informacje lub funkcje edycji.
Widok ucznia to strona, która jest wyświetlana każdemu uczniowi po otwarciu załącznika dodatku.
Na potrzeby tego ćwiczenia utwórz jedną /load-content-attachment
trasę, która będzie obsługiwać zarówno widok nauczyciela, jak i widok ucznia. Użyj metod interfejsu Classroom API, aby określić, czy użytkownik jest nauczycielem czy uczniem, gdy strona się wczytuje.
Python
W naszym przykładzie jest to plik 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")
Pamiętaj, że na tym etapie musisz też uwierzytelnić użytkownika. Musisz też obsłużyć parametr zapytania login_hint
i w razie potrzeby przekierować użytkownika do procesu autoryzacji. Więcej informacji o tym procesie znajdziesz w szczegółowych wskazówkach dotyczących logowania, które zostały omówione w poprzednich przewodnikach.
Następnie wyślij żądanie do punktu końcowego getAddOnContext
, który pasuje do typu elementu.
Python
W naszym przykładzie jest to kontynuacja metody 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()
Ta metoda zwraca informacje o roli bieżącego użytkownika w klasie.
zmieniać widok prezentowany użytkownikowi w zależności od jego roli; W obiekcie odpowiedzi wypełnione jest dokładnie jedno z pól studentContext
lub teacherContext
. Sprawdź te informacje, aby określić, jak zwrócić się do użytkownika.
W każdym przypadku użyj wartości parametru zapytania attachmentId
, aby dowiedzieć się, który załącznik pobrać z naszej bazy danych. Ten parametr zapytania jest podawany podczas otwierania identyfikatorów URI widoku nauczyciela lub ucznia.
Python
W naszym przykładzie jest to kontynuacja metody 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)
Testowanie dodatku
Aby przetestować tworzenie załączników:
- Zaloguj się w [Google Classroom] jako jeden z użytkowników testowych z rolą nauczyciela.
- Przejdź do karty Zadania i utwórz nowy projekt.
- Kliknij przycisk Dodatki pod obszarem tekstu, a następnie wybierz dodatek. Otworzy się element iframe, a dodatek wczyta identyfikator URI konfiguracji załącznika, który został określony na stronie Konfiguracja aplikacji w pakiecie SDK Google Workspace Marketplace.
- Wybierz treść, którą chcesz dołączyć do projektu.
- Zamknij element iframe po zakończeniu procesu tworzenia załącznika.
W interfejsie tworzenia projektu w Google Classroom powinna pojawić się karta załącznika. Kliknij kartę, aby otworzyć element iframe Widok nauczyciela i potwierdzić, że wyświetla się prawidłowy załącznik. Kliknij przycisk Przypisz.
Aby przetestować środowisko ucznia:
- Następnie zaloguj się w Classroom jako uczeń testowy w tej samej klasie co nauczyciel testowy.
- Znajdź projekt testowy na karcie Zadania.
- Rozwiń projekt i kliknij kartę załącznika, aby otworzyć ramkę iframe Widok ucznia.
Sprawdź, czy uczeń widzi właściwy załącznik.
Gratulacje! Możesz przejść do następnego kroku: tworzenia załączników typu aktywności.