Załączniki typu aktywności

To piąty przewodnik z serii przewodników po dodatkach do Classroom.

W tym przewodniku zmodyfikujesz przykład z poprzedniego kroku, aby utworzyć załącznik typu aktywność. Są to załączniki, które wymagają przesłania przez ucznia odpowiedzi, np. pisemnej, testu lub innego artefaktu utworzonego przez ucznia.

Ważne jest rozróżnienie między załącznikami typu treść a załącznikami typu aktywność. Załączniki typu aktywność różnią się od załączników typu treść w następujący sposób:

  • W prawym górnym rogu elementu iframe Widok ucznia pojawia się przycisk „Oddaj”.
  • Zawierają unikalny identyfikator pracy ucznia.
  • Ich karta załącznika pojawia się w interfejsie oceniania w Classroom.
  • Mogą ustawić ocenę za projekt, do którego należą.

Więcej informacji o ocenianiu znajdziesz w następnym przewodniku. W tym przewodniku wykonasz te czynności:

  • Zmodyfikujesz poprzednie żądania utworzenia załącznika do interfejsu Classroom API, aby utworzyć załącznik typu aktywność.
  • Wdrożysz pamięć trwałą dla zadań przesłanych przez uczniów.
  • Zmodyfikujesz poprzednią trasę Widok ucznia, aby akceptować dane wejściowe od uczniów.
  • Udostępnisz trasę do wyświetlania elementu iframe Sprawdzanie prac uczniów.

Po zakończeniu tych czynności możesz tworzyć załączniki typu aktywność w projektach w interfejsie Google Classroom, gdy zalogujesz się jako nauczyciel. Uczniowie na zajęciach mogą też wykonać aktywność w elemencie iframe i przesłać odpowiedź. Nauczyciel może wyświetlić zadanie przesłane przez ucznia w interfejsie oceniania w Classroom.

Na potrzeby tego przykładu ponownie użyj szablonu załącznika z poprzedniego przewodnika, który zawiera obraz znanego zabytku i podpis z jego nazwą. Aktywność polega na poproszeniu ucznia o podanie nazwy zabytku.

Modyfikowanie żądania utworzenia załącznika

Przejdź do tej części kodu, w której w poprzednim przewodniku utworzono załącznik typu treść. Kluczowym elementem jest tu instancja obiektu AddOnAttachment, w której wcześniej określiliśmy pola teacherViewUri, studentViewUri, i title załącznika.

Chociaż wszystkie załączniki dodatku wymagają tych 3 pól, obecność lub brak pola studentWorkReviewUri decyduje o tym, czy załącznik jest typu aktywność czy typu treść. Żądanie CREATE z wypełnionym polem studentWorkReviewUri staje się załącznikiem typu aktywność, a żądanie CREATE bez pola studentWorkReviewUri staje się załącznikiem typu treść.

Jedyna zmiana, jaką musisz wprowadzić w tym żądaniu, to wypełnienie pola studentWorkReviewUri. Dodaj tutaj trasę o odpowiedniej nazwie. Zaimplementujesz ją w późniejszym kroku.

Python

W podanym przez nas przykładzie znajduje się ona w metodzie create_attachments w pliku webapp/attachment_routes.py.

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    # The presence of this field marks this as an activity-type attachment.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

Dodawanie pamięci trwałej dla załączników typu treść

Zapisz odpowiedź ucznia na naszą aktywność. Możesz ją później wyszukać, gdy nauczyciel wyświetli zadanie w elemencie iframe Sprawdzanie prac uczniów.

Skonfiguruj schemat bazy danych dla Submission. W podanym przez nas przykładzie uczniowie mają wpisać nazwę zabytku pokazanego na obrazie. Dlatego Submission zawiera te atrybuty:

  • attachment_id: unikalny identyfikator załącznika. Przypisany przez Classroom i zwrócony w odpowiedzi podczas tworzenia załącznika.
  • submission_id: identyfikator zadania przesłanego przez ucznia. Przypisany przez Classroom i zwrócony w getAddOnContext odpowiedzi w Widoku ucznia.
  • student_response: odpowiedź ucznia.

Python

Rozszerz implementację SQLite i flask_sqlalchemy z poprzednich kroków.

Otwórz plik, w którym zdefiniowano poprzednie tabele (models.py, jeśli korzystasz z podanego przez nas przykładu). Na końcu pliku dodaj ten kod.

# Database model to represent a student submission.
class Submission(db.Model):
    # The attachmentId is the unique identifier for the attachment.
    submission_id = db.Column(db.String(120), primary_key=True)

    # The unique identifier for the student's submission.
    attachment_id = db.Column(db.String(120), primary_key=True)

    # The student's response to the question prompt.
    student_response = db.Column(db.String(120))

Zaimportuj nową klasę Submission do pliku serwera z trasami obsługi załączników.

Modyfikowanie trasy Widok ucznia

Następnie zmodyfikuj poprzednią trasę Widok ucznia, aby wyświetlać mały formularz i akceptować dane wejściowe od ucznia. Możesz ponownie użyć większości kodu z poprzedniego przewodnika.

Znajdź kod serwera, który udostępnia trasę dla Widoku ucznia. Jest to trasa określona w polu studentViewUri podczas tworzenia załącznika. Pierwsza zmiana, jaką musisz wprowadzić, to wyodrębnienie submissionId z getAddOnContext odpowiedzi.

Python

W podanym przez nas przykładzie znajduje się ona w metodzie load_activity_attachment w pliku webapp/attachment_routes.py.

# Issue a request to the courseWork.getAddOnContext endpoint
addon_context_response = classroom_service.courses().courseWork(
).getAddOnContext(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"]).execute()

# One of studentContext or teacherContext will be populated.
user_context = "student" if addon_context_response.get(
    "studentContext") else "teacher"

# If the user is a student...
if user_context == "student":
    # Extract the submissionId from the studentContext object.
    # This value is provided by Google Classroom.
    flask.session["submissionId"] = addon_context_response.get(
            "studentContext").get("submissionId")

Możesz też wysłać żądanie, aby uzyskać stan zadania przesłanego przez ucznia. Odpowiedź zawiera wartość SubmissionState, która wskazuje stany, np. czy uczeń otworzył załącznik lub go oddał. Może to być przydatne, jeśli chcesz uniemożliwić edytowanie oddanego zadania lub jeśli chcesz udostępnić nauczycielowi statystyki dotyczące postępów uczniów:

Python

W podanym przez nas przykładzie jest to kontynuacja metody load_activity_attachment opisanej powyżej.

# Issue a request to get the status of the student submission.
submission_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().get(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"]).execute()

Na koniec pobierz informacje o załączniku z naszej bazy danych i wyświetl formularz wprowadzania danych. Formularz w podanym przez nas przykładzie składa się z pola do wprowadzania danych i przycisku przesyłania. Wyświetl obraz zabytku i poproś ucznia o wpisanie jego nazwy. Gdy uczeń poda odpowiedź, zapisz ją w naszej bazie danych.

Python

W podanym przez nas przykładzie jest to kontynuacja metody load_activity_attachment opisanej powyżej.

# Look up the attachment in the database.
attachment = Attachment.query.get(flask.session["attachmentId"])

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 complete the activity below.")

form = activity_form_builder()

if form.validate_on_submit():
    # Record the student's response in our database.

    # Check if the student has already submitted a response.
    # If so, update the response stored in the database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    if student_submission is not None:
        student_submission.student_response = form.student_response.data
    else:
        # Store the student's response by the submission ID.
        new_submission = Submission(
            submission_id=flask.session["submissionId"],
            attachment_id=flask.session["attachmentId"],
            student_response=form.student_response.data)
        db.session.add(new_submission)

    db.session.commit()

    return flask.render_template(
        "acknowledge-submission.html",
        message="Your response has been recorded. You can close the " \
            "iframe now.",
        instructions="Please Turn In your assignment if you have " \
            "completed all tasks."
    )

# Show the activity.
return flask.render_template(
    "show-activity-attachment.html",
    message=message_str,
    image_filename=attachment.image_filename,
    image_caption=attachment.image_caption,
    user_context=user_context,
    form=form,
    responses=response_strings)

Aby odróżnić użytkowników, możesz wyłączyć funkcję przesyłania i zamiast tego wyświetlić prawidłową odpowiedź w Widoku nauczyciela.

Dodawanie trasy dla elementu iframe Sprawdzanie prac uczniów

Na koniec dodaj trasę do wyświetlania elementu iframe Sprawdzanie prac uczniów. Nazwa tej trasy powinna być zgodna z nazwą podaną w polu studentWorkReviewUri podczas tworzenia załącznika. Ta trasa otwiera się, gdy nauczyciel wyświetla zadanie przesłane przez ucznia w interfejsie oceniania w Classroom.

Gdy Classroom otworzy element iframe Sprawdzanie prac uczniów, otrzymasz parametr zapytania submissionId. Użyj go, aby pobrać pracę ucznia z lokalnej bazy danych:

Python

W podanym przez nas przykładzie znajduje się ona w pliku webapp/attachment_routes.py.

@app.route("/view-submission")
def view_submission():
    """
    Render a student submission using the show-student-submission.html template.
    """

    # Save the query parameters passed to the iframe in the session, just as we did
    # in previous routes. Abbreviated here for readability.
    add_iframe_query_parameters_to_session(flask.request.args)

    # For the sake of brevity in this example, we'll skip the conditional logic
    # to see if we need to authorize the user as we have done in previous steps.
    # We can assume that the user that reaches this route is a teacher that has
    # already authorized and created an attachment using the add-on.

    # In production, we recommend fully validating the user's authorization at
    # this stage as well.

    # Look up the student's submission in our database.
    student_submission = Submission.query.get(flask.session["submissionId"])

    # Look up the attachment in the database.
    attachment = Attachment.query.get(student_submission.attachment_id)

    # Render the student's response alongside the correct answer.
    return flask.render_template(
        "show-student-submission.html",
        message=f"Loaded submission {student_submission.submission_id} for "\
            f"attachment {attachment.attachment_id}.",
        student_response=student_submission.student_response,
        correct_answer=attachment.image_caption)

Testowanie dodatku

Powtórz kroki opisane w sekcji Testowanie dodatku w poprzednim przewodniku. Powinien być dostępny załącznik, który uczeń może otworzyć.

Aby przetestować załącznik aktywności:

  • Zaloguj się w Google Classroom jako jeden z użytkowników testowych (uczniów) w tej samej klasie co użytkownik testowy (nauczyciel).
  • Otwórz kartę Zadania i rozwiń testowy projekt.
  • Kliknij kartę załącznika dodatku , aby otworzyć Widok ucznia i przesłać odpowiedź na aktywność.
  • Po zakończeniu aktywności zamknij element iframe. Opcjonalnie kliknij przycisk Oddaj.

Po zakończeniu aktywności nie powinny wystąpić żadne zmiany w Classroom. Teraz przetestuj element iframe Sprawdzanie prac uczniów:

  • Zaloguj się w Classroom jako nauczyciel użytkownik testowy.
  • Na karcie Oceny znajdź kolumnę z testowym projektem. Kliknij nazwę testowego projektu.
  • Znajdź kartę testowego ucznia. Kliknij załącznik na karcie.

Sprawdź, czy uczeń widzi prawidłowe zadanie.

Gratulacje! Możesz przejść do następnego kroku: synchronizowania ocen załączników.