Pièces jointes liées à l'activité

Il s'agit du cinquième tutoriel de la série de tutoriels sur les modules complémentaires Classroom.

Dans ce tutoriel, vous allez modifier l'exemple de l'étape précédente pour générer un rattachement de type activité. Il s'agit de toutes les pièces jointes nécessitant un envoi par un élève, telles qu'une réponse écrite, un questionnaire ou tout autre artefact généré par l'élève.

La distinction entre les pièces jointes par type de contenu et par type d'activité est importante. Les pièces jointes de type "activité" et "content-type" présentent les différences suivantes:

  • Un bouton "Rendre le devoir" s'affiche en haut à droite de l'iFrame de la vue des élèves.
  • Ils permettent d'identifier de manière unique les devoirs des élèves.
  • La fiche de la pièce jointe s'affiche dans l'interface utilisateur de l'outil de notation Classroom.
  • Il peut attribuer une note au devoir auquel il appartient.

Consultez le tutoriel suivant pour en savoir plus sur la notation. Au cours de ce tutoriel, vous allez effectuer les opérations suivantes:

  • Modifiez les requêtes de création de pièces jointes précédentes vers l'API Classroom pour créer une pièce jointe de type activité.
  • Implémentez un stockage persistant pour les devoirs rendus par les élèves.
  • Modifiez l'itinéraire précédent de la vue des élèves pour accepter les entrées des élèves.
  • Indiquez un itinéraire pour diffuser l'iFrame "Devoirs des élèves".

Une fois que vous avez terminé, lorsque vous êtes connecté en tant qu'enseignant, vous pouvez joindre des types d'activités aux devoirs via l'interface utilisateur de Google Classroom. Les élèves peuvent également réaliser l'activité dans l'iFrame et envoyer une réponse. L'enseignant peut voir le devoir envoyé par l'élève dans l'interface de notation de Classroom.

Pour les besoins de cet exemple, réutilisez le modèle de pièce jointe du tutoriel précédent, qui montre une image d'un point de repère célèbre et une légende avec le nom de ce point de repère. L'activité consiste à inviter l'élève à fournir le nom du point de repère.

Modifier la demande de création de pièce jointe

Accédez à la section du code dans laquelle vous avez créé une pièce jointe de type de contenu dans le tutoriel précédent. L'élément clé ici est une instance d'un objet AddOnAttachment dans lequel nous avons précédemment spécifié les valeurs teacherViewUri, studentViewUri et title pour le rattachement.

Bien que tous les rattachements de modules complémentaires nécessitent ces trois champs, la présence ou l'absence d'un studentWorkReviewUri détermine s'ils sont de type activité ou de type contenu. Une requête CREATE avec un studentWorkReviewUri renseigné devient un rattachement de type d'activité, tandis qu'une requête CREATE sans studentWorkReviewUri devient un rattachement de contenu.

La seule modification à apporter à cette requête consiste à renseigner le champ studentWorkReviewUri. Ajoutez ici un itinéraire portant le nom approprié. Vous l'implémenterez ultérieurement.

Python

Dans l'exemple fourni, cette méthode se trouve dans la méthode create_attachments du fichier 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}",
}

Ajouter un espace de stockage persistant pour les pièces jointes de type contenu

Notez la réponse de l'élève à notre activité. Vous pourrez le consulter plus tard, lorsque l'enseignant affichera le devoir dans l'iFrame "Devoirs des élèves".

Configurez un schéma de base de données pour un élément Submission. Dans l'exemple fourni, les élèves doivent saisir le nom du point de repère indiqué sur une image. Un Submission contient donc les attributs suivants:

  • attachment_id: identifiant unique d'une pièce jointe. Attribué par Classroom et renvoyé dans la réponse lors de la création d'une pièce jointe.
  • submission_id: identifiant d'un devoir envoyé par un élève. Attribué par Classroom et renvoyé dans la réponse getAddOnContext de la vue élève.
  • student_response: réponse fournie par l'élève.

Python

Étendez l'implémentation de SQLite et de flask_sqlalchemy à partir des étapes précédentes.

Accédez au fichier dans lequel vous avez défini les tables précédentes (models.py si vous suivez l'exemple fourni). Ajoutez le code suivant en bas du fichier.

# 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))

Importez la nouvelle classe Submission dans le fichier serveur avec vos routes de gestion des pièces jointes.

Modifier l'itinéraire Student View

Modifiez ensuite l'itinéraire précédent pour afficher un petit formulaire et accepter les commentaires de l'élève. Vous pouvez réutiliser la majeure partie du code du tutoriel précédent.

Repérez le code serveur qui fournit l'itinéraire pour votre vue élève. Il s'agit de la route spécifiée dans le champ studentViewUri lors de la création d'un rattachement. La première modification à effectuer consiste à extraire le submissionId de la réponse getAddOnContext.

Python

Dans l'exemple fourni, cette méthode se trouve dans la méthode load_activity_attachment du fichier 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")

Vous pouvez également envoyer une demande pour connaître l'état du travail d'un élève. La réponse contient une valeur SubmissionState, qui indique des états tels que si l'élève a ouvert la pièce jointe ou l'a rendue. Cela peut être utile si vous souhaitez interdire la modification d'un devoir remis ou si vous souhaitez fournir aux enseignants des informations sur la progression de leurs élèves:

Python

Dans l'exemple fourni, il s'agit d'une continuation de la méthode load_activity_attachment ci-dessus.

# 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()

Enfin, récupérez les informations sur la pièce jointe dans notre base de données et envoyez un formulaire de saisie. Dans l'exemple fourni, le formulaire se compose d'un champ de saisie de type chaîne et d'un bouton "Envoyer". Affichez l'image du point de repère et invitez l'élève à saisir son nom. Une fois qu'il a fourni une réponse, enregistrez-la dans notre base de données.

Python

Dans l'exemple fourni, il s'agit d'une continuation de la méthode load_activity_attachment ci-dessus.

# 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)

Pour différencier les utilisateurs, envisagez de désactiver la fonction d'envoi et d'afficher la bonne réponse dans la vue "Enseignant".

Ajouter un itinéraire pour l'iFrame "Devoirs des élèves"

Enfin, ajoutez un itinéraire pour diffuser l'iFrame "Devoirs des élèves". Le nom de cette route doit correspondre à celui fourni pour le champ studentWorkReviewUri lors de la création d'un rattachement. Cette route s'ouvre lorsque l'enseignant affiche le devoir de l'élève dans l'interface utilisateur de l'outil de notation Classroom.

Vous recevez le paramètre de requête submissionId lorsque Classroom ouvre l'iFrame de l'examen des devoirs des élèves. Utilisez-la pour récupérer le travail de l'élève dans votre base de données locale:

Python

Dans l'exemple fourni, il se trouve dans le fichier 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)

Tester le module complémentaire

Répétez la procédure Tester les étapes du module complémentaire du tutoriel précédent. Vous devez avoir une pièce jointe que l'élève peut ouvrir.

Procédez comme suit pour tester la pièce jointe à l'activité:

  • Connectez-vous à Google Classroom en tant qu'utilisateur test élève de la même classe que l'utilisateur test de l'enseignant.
  • Accédez à l'onglet Travaux et devoirs et développez le test Devoir.
  • Cliquez sur la fiche du module complémentaire en pièce jointe pour ouvrir la vue élève et envoyer une réponse pour l'activité.
  • Une fois l'activité terminée, fermez l'iFrame. Vous pouvez également cliquer sur le bouton Rendre.

Vous ne devriez constater aucun changement dans Classroom une fois l'activité terminée. Testez maintenant l'iFrame de l'examen des devoirs des élèves:

  • Connectez-vous à Classroom en tant qu'utilisateur test enseignant.
  • Recherchez la colonne correspondant à votre devoir dans l'onglet Notes. Cliquez sur le nom de votre devoir de test.
  • Recherchez la fiche de l'élève test. Cliquez sur la pièce jointe sur la fiche.

Vérifiez que le devoir correct s'affiche pour l'élève.

Félicitations ! Vous êtes prêt à passer à l'étape suivante: synchroniser les notes des pièces jointes.