Załączniki typu aktywności

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

W tym przewodniku zmodyfikujesz przykład z poprzedniego kroku, aby utworzyć przyłącze typu activity. To wszystkie załączniki, które wymagają przesłania przez ucznia, np. pisemna odpowiedź, quiz lub inny artefakt wygenerowany przez ucznia.

Rozróżnienie między załącznikami typu treści i aktywności jest bardzo ważne. Załączniki do rodzaju aktywności różnią się od typu treści pod kilkoma względami:

  • W prawym górnym rogu elementu iframe Widok ucznia pojawi się przycisk „Oddaj”.
  • Zapewniają unikalny identyfikator zadań uczniów.
  • Karta załącznika pojawi się w interfejsie osoby oceniającej Classroom.
  • Mogą ustawić ocenę za projekt, do którego należą.

Zapoznaj się z następnym przewodnikiem, aby dowiedzieć się więcej o ocenianiu. W ramach tego przewodnika wykonasz te czynności:

  • Zmodyfikuj poprzednie żądania tworzenia załączników do interfejsu Classroom API, aby utworzyć załącznik typu aktywność.
  • Zadbaj o to, aby materiały przesłane przez uczniów były przechowywane w stałym miejscu.
  • Zmodyfikuj poprzednią trasę widoku uczniów, aby zaakceptować dane wejściowe uczniów.
  • Podaj trasę wyświetlania elementu iframe z oceną zadań uczniów.

Gdy skończysz, możesz tworzyć załączniki do projektów w interfejsie Google Classroom po zalogowaniu się jako nauczyciel. Uczniowie mogą też wykonać działanie w elemencie iframe i przesłać odpowiedź. Nauczyciel może wyświetlić zadanie przesłane przez ucznia w interfejsie oceniania Classroom.

Na potrzeby tego przykładu użyj szablonu załącznika z poprzedniego przewodnika, który zawiera zdjęcie znanego punktu orientacyjnego i podpis z jego nazwą. Ćwiczenie polega na proszeniu ucznia o podanie nazwy punktu orientacyjnego.

Zmień żądanie utworzenia załącznika

Przejdź do sekcji kodu, w której w poprzednim przewodniku utworzony został załącznik typu content-type. Elementem klucza w tym miejscu jest wystąpienie obiektu AddOnAttachment, w którym określono wcześniej teacherViewUri, studentViewUri i title dla załącznika.

Wszystkie załączniki dodatków wymagają tych 3 pól, ale obecność lub brak atrybutu studentWorkReviewUri określa, czy załącznik to rodzaj aktywności czy typ treści. Żądanie CREATE z wypełnionym elementem studentWorkReviewUri staje się załącznikiem typu działania, a żądanie CREATE bez parametru studentWorkReviewUri staje się załącznikiem typu treści.

Jedyną modyfikacją, jaką możesz wprowadzić w tym żądaniu, jest wypełnienie pola studentWorkReviewUri. Dodaj tutaj odpowiednią trasę. Zaimplementujesz ją w późniejszym kroku.

Python

W podanym przykładzie jest to metoda 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}",
}

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

Zapisuj odpowiedź ucznia na zadanie. Możesz ją później znaleźć, gdy nauczyciel wyświetli przesłane zadanie w elemencie iframe z oceną zadań uczniów.

Skonfiguruj schemat bazy danych dla: Submission. W naszym przykładzie uczniowie muszą wpisać nazwę punktu orientacyjnego przedstawionego na ilustracji. Submission zawiera więc te atrybuty:

  • attachment_id: unikalny identyfikator załącznika. Przypisywane przez Classroom i zwracane w odpowiedzi podczas tworzenia załącznika.
  • submission_id: identyfikator zadania przesłanego przez ucznia. Przypisane przez Classroom i zwrócone w odpowiedzi getAddOnContext w widoku ucznia.
  • student_response: odpowiedź podana przez ucznia.

Python

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

Przejdź do pliku, w którym są zdefiniowane poprzednie tabele (models.py, jeśli korzystasz z podanego przykładu). Dodaj poniższy kod na dole pliku.

# 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 widoku ucznia

Następnie zmodyfikuj poprzednią trasę widoku uczniów, aby wyświetlić mały formularz i przyjąć dane od ucznia. Możesz ponownie wykorzystać większość kodu z poprzedniego przewodnika.

Znajdź kod serwera, który wyznacza trasę do widoku ucznia. To jest trasa określona w polu studentViewUri podczas tworzenia załącznika. Pierwszą zmianą jest wyodrębnienie funkcji submissionId z odpowiedzi getAddOnContext.

Python

W podanym przykładzie jest to metoda 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ć prośbę o sprawdzenie stanu zadania przesłanego przez ucznia. Odpowiedź zawiera wartość SubmissionState, która wskazuje np., czy uczeń otworzył załącznik, czy go oddał. Może to być przydatne, jeśli chcesz zablokować możliwość edytowania oddanych zadań lub chcesz przekazywać nauczycielom informacje o postępach uczniów:

Python

W podanym 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 udostępnij formularz do wprowadzania danych. Formularz w tym przykładzie składa się z pola do wprowadzania ciągu znaków i przycisku Prześlij. Pokaż obraz punktu orientacyjnego i poproś ucznia o wpisanie imienia i nazwiska. Po udzieleniu odpowiedzi zapisz ją w naszej bazie danych.

Python

W podanym 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 rozróżnić użytkowników, możesz wyłączyć funkcję przesyłania i zamiast tego wyświetlać poprawną odpowiedź w widoku nauczyciela.

Dodawanie trasy na potrzeby elementu iframe z oceną zadań uczniów

Na koniec dodaj trasę wyświetlania elementu iframe z oceną zadań uczniów. Nazwa tej trasy powinna być zgodna z nazwą w polu studentWorkReviewUri podczas tworzenia załącznika. Ta trasa jest otwierana, gdy nauczyciel wyświetli zadanie przesłane przez ucznia w interfejsie osoby oceniającej Classroom.

Parametr zapytania submissionId pojawia się, gdy Classroom otworzy element iframe z oceną zadań uczniów. Użyj go, aby pobrać pracę ucznia z lokalnej bazy danych:

Python

W podanym przykładzie znajduje się on 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 czynności z sekcji Testowanie dodatku z poprzedniego przewodnika. Powinieneś mieć załącznik, który uczeń może otworzyć.

Aby przetestować przyłącze do działania, wykonaj te czynności:

  • Zaloguj się w Google Classroom jako jeden z uczniów testowych korzystających z tych samych zajęć co nauczyciel.
  • Otwórz kartę Zadania i rozwiń Projekt testowy.
  • Kliknij kartę załącznika dodatku, aby otworzyć widok ucznia i przesłać odpowiedź do zadania.
  • Po zakończeniu aktywności zamknij element iframe. Opcjonalnie kliknij przycisk Oddaj.

Po jego ukończeniu nie powinno być żadnych zmian. Teraz sprawdź element iframe z opiniami uczniów:

  • Zaloguj się w Classroom jako użytkownik testowy jako nauczyciel.
  • Znajdź kolumnę projektu testowego na karcie Oceny. Kliknij nazwę projektu testowego.
  • Znajdź kartę użytkownika egzaminacyjnego. Kliknij załącznik na karcie.

Sprawdź, czy uczeń zobaczy właściwe zadanie.

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