Załączniki typu aktywności

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

W tym przewodniku zmodyfikujesz przykład z poprzedniego kroku, aby utworzyć załącznik typu działania. Są to załączniki wymagające przesłania przez ucznia, np. pisemna odpowiedź, test lub inne artefakty wygenerowane przez uczniów.

Rozróżnienie między załącznikami typu treści i aktywności jest istotne. Załączniki związane z aktywnością różnią się od typu treści pod tym względem:

  • W prawym górnym rogu elementu iframe widoku ucznia pojawi się przycisk „Oddaj”.
  • Zapewniają unikalny identyfikator pracy ucznia.
  • Karta załącznika wyświetla się w interfejsie ucznia do oceniania w Classroom.
  • Mogą też ustawić ocenę za projekt, do którego należą.

W następnym przewodniku znajdziesz opis sposobu oceniania. W trakcie tego przewodnika wykonaj te czynności:

  • Zmodyfikuj poprzednie żądania utworzenia załączników do interfejsu Classroom API, aby utworzyć załącznik typu aktywności.
  • Wdróż trwałe przechowywanie prac uczniów.
  • Zmodyfikuj poprzednią trasę widoku ucznia, aby akceptować dane wejściowe ucznia.
  • Podaj trasę do wyświetlania elementu iframe z recenzją pracy ucznia.

Po zakończeniu pracy możesz tworzyć załączniki aktywności w projektach w interfejsie Google Classroom po zalogowaniu się jako nauczyciel. Uczniowie na zajęciach mogą też wykonać to 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 wykorzystaj ponownie szablon załącznika z poprzedniego przewodnika, który przedstawia obraz słynnego punktu orientacyjnego i podpis z jego nazwą. W ramach zadania uczeń musi podać nazwę punktu orientacyjnego.

Modyfikowanie prośby o utworzenie załącznika

Przejdź do sekcji kodu, w której masz utworzony załącznik content-type w poprzednim przewodniku. Kluczowym elementem w tym miejscu jest instancja obiektu AddOnAttachment, w którym wcześniej określaliśmy właściwości teacherViewUri, studentViewUri i title załącznika.

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

Jedyną zmianą, jaką należy wprowadzić w żądaniu, jest wypełnienie pola studentWorkReviewUri. Dodaj tutaj trasę o odpowiedniej nazwie. Wdrożysz ją w następnym kroku.

Python

W podanym przykładzie znajduje się to 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}",
}

Dodaj pamięć trwałą na załączniki typu treści

Zapisz odpowiedź ucznia na naszą aktywność. Możesz sprawdzić je później, gdy nauczyciel wyświetli przesłane zadanie w elemencie iframe z oceną pracy ucznia.

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

  • attachment_id: unikalny identyfikator załącznika. Przypisane 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 zostały zdefiniowane poprzednie tabele (models.py, jeśli korzystasz z podanego przykładu). Na dole pliku dodaj:

# 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ę w widoku ucznia, aby wyświetlić mały formularz i zaakceptować informacje od ucznia. Możesz ponownie wykorzystać większość kodu z poprzedniej instrukcji.

Znajdź kod serwera udostępniający trasę widoku ucznia. Jest to trasa podana w polu studentViewUri podczas tworzenia przyłącza. Pierwszą zmianą jest wyodrębnienie pola submissionId z odpowiedzi getAddOnContext.

Python

W podanym przykładzie znajduje się to 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ż przesłać prośbę o sprawdzenie stanu zadania przesłanego przez ucznia. Odpowiedź zawiera wartość SubmissionState, która wskazuje na przykład, czy uczeń otworzył załącznik, czy go oddał. Może to być przydatne, jeśli nie chcesz edytować oddanego zadania lub chcesz przekazać nauczycielom informacje o postępach uczniów:

Python

W podanym przykładzie jest to kontynuacja powyższej metody load_activity_attachment.

# 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łącznikach z naszej bazy danych i udostępnij im formularz do wprowadzania danych. Formularz w naszym przykładzie składa się z pola do wprowadzania ciągu znaków i przycisku przesyłania. Pokaż obraz punktu orientacyjnego i poproś ucznia o wpisanie jego imienia i nazwiska. Gdy udzielą odpowiedzi, zapisz ją w naszej bazie danych.

Python

W podanym przykładzie jest to kontynuacja powyższej metody load_activity_attachment.

# 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óżniać użytkowników, możesz wyłączyć funkcję przesyłania i zamiast tego wyświetlać prawidłową odpowiedź w widoku nauczyciela.

Dodawanie trasy do elementu iframe z oceną pracy ucznia

Na koniec dodaj trasę, która będzie wyświetlać element iframe z oceną pracy ucznia. Nazwa tej trasy powinna być zgodna z nazwą podaną dla elementu studentWorkReviewUri podczas tworzenia przyłącza. Ta trasa otwiera się, gdy nauczyciel wyświetla zadanie przesłane przez ucznia w interfejsie oceniania w Classroom.

Gdy Classroom otworzy element iframe Podsumowanie pracy ucznia, otrzymasz parametr zapytania submissionId. Za jego pomocą możesz pobrać pracę ucznia z lokalnej bazy danych:

Python

W naszym przykładzie znajduje się to 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 Przetestuj kroki dodatku z poprzedniego przewodnika. Powinieneś mieć załącznik, który może otworzyć uczeń.

Aby przetestować załącznik, wykonaj te czynności:

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

Po wykonaniu tego ćwiczenia w Classroom nie powinno się zmienić. Teraz przetestuj element iframe z oceną pracy ucznia:

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

Sprawdź, czy uczeń wyświetla poprawne zadanie.

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