Archivos adjuntos de tipo de actividad

Esta es la quinta explicación de la serie de instructivos sobre complementos de Classroom.

En esta explicación, modificas el ejemplo del paso anterior de la explicación para producir un archivo adjunto de tipo de actividad. Son todos los archivos adjuntos que requieren que los estudiantes envíen contenido, como una respuesta escrita, un cuestionario o cualquier otro artefacto generado por el estudiante.

Es importante distinguir entre los archivos adjuntos de tipo de contenido y de tipo de actividad. Los archivos adjuntos de tipo de actividad difieren de los de tipo de contenido de las siguientes maneras:

  • Aparecerá un botón “Enviar” en la parte superior derecha del iframe de la vista del estudiante.
  • Proporcionan un identificador único para el trabajo de los estudiantes.
  • La tarjeta del archivo adjunto aparecerá en la IU del calificador de Classroom.
  • Pueden establecer una calificación para la tarea a la que pertenecen.

Consulta la siguiente explicación para obtener información sobre la calificación. En el transcurso de esta explicación, completarás lo siguiente:

  • Modifica las solicitudes de creación de archivos adjuntos anteriores a la API de Classroom para crear un archivo adjunto de tipo de actividad.
  • Implementa el almacenamiento persistente para los envíos de los estudiantes.
  • Modifica la ruta de acceso anterior de la vista del estudiante para aceptar la entrada del estudiante.
  • Proporciona una ruta para publicar el iframe de Student Work Review.

Cuando termines, podrás crear archivos adjuntos de tipo de actividad en las tareas a través de la IU de Google Classroom cuando accedas como profesor. Los estudiantes de la clase también pueden completar la actividad en el iframe y enviar una respuesta. El profesor puede ver el trabajo que envió el alumno en la IU de calificación de Classroom.

A los efectos de este ejemplo, reutiliza la plantilla de archivo adjunto de la explicación anterior, que muestra una imagen de un lugar famoso y una leyenda con el nombre del lugar. La actividad consiste en pedirle al estudiante que proporcione el nombre del punto de referencia.

Modifica la solicitud de creación de archivos adjuntos

Navega a la sección de tu código en la que creaste un archivo adjunto de tipo de contenido en la explicación anterior. El elemento clave aquí es una instancia de un objeto AddOnAttachment, en el que especificamos anteriormente teacherViewUri, studentViewUri y title para el archivo adjunto.

Si bien todos los archivos adjuntos de complementos requieren estos tres campos, la presencia o ausencia de un studentWorkReviewUri determina si el archivo adjunto es de tipo de actividad o de tipo de contenido. Una solicitud CREATE con un studentWorkReviewUri propagado se convierte en un archivo adjunto de tipo de actividad, mientras que una solicitud CREATE sin un studentWorkReviewUri se convierte en un archivo adjunto de tipo de contenido.

La única modificación que se debe realizar en esta solicitud es propagar el campo studentWorkReviewUri. Agrega una ruta con un nombre adecuado aquí. La implementarás en un paso posterior.

Python

En nuestro ejemplo proporcionado, esto se encuentra en el método create_attachments del archivo 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}",
}

Agrega almacenamiento persistente para archivos adjuntos de tipo de contenido

Registra la respuesta del estudiante a nuestra actividad. Puedes buscarlo más tarde cuando el profesor vea el envío en el iframe de Revisión de trabajos de los estudiantes.

Configura un esquema de base de datos para un Submission. En nuestro ejemplo, se espera que los estudiantes ingresen el nombre del punto de referencia que se muestra en una imagen. Por lo tanto, un Submission contiene los siguientes atributos:

  • attachment_id: Es un identificador único para un archivo adjunto. Se asigna en Classroom y se muestra en la respuesta cuando se crea un archivo adjunto.
  • submission_id: Es un identificador para el envío de un estudiante. Se asigna en Classroom y se muestra en la respuesta getAddOnContext de la vista de estudiante.
  • student_response: Es la respuesta que proporcionó el estudiante.

Python

Extiende la implementación de SQLite y flask_sqlalchemy de los pasos anteriores.

Navega al archivo en el que definiste las tablas anteriores (models.py si sigues nuestro ejemplo proporcionado). Agrega lo siguiente al final del archivo.

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

Importa la nueva clase Submission en el archivo del servidor con tus rutas de manejo de archivos adjuntos.

Modifica la ruta de la vista de estudiante

A continuación, modifica la ruta de acceso anterior de la vista del estudiante para mostrar un formulario pequeño y aceptar la entrada del estudiante. Puedes reutilizar la mayor parte del código del recorrido anterior.

Busca el código del servidor que proporciona la ruta de tu vista de estudiante. Esta es la ruta especificada en el campo studentViewUri cuando se crea un archivo adjunto. El primer cambio que debes hacer es extraer el submissionId de la respuesta getAddOnContext.

Python

En nuestro ejemplo proporcionado, esto se encuentra en el método load_activity_attachment del archivo 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")

También puedes enviar una solicitud para obtener el estado de entrega del estudiante. La respuesta contiene un valor SubmissionState, que indica estados, como si el estudiante abrió el archivo adjunto o lo entregó. Esto puede ser útil si quieres impedir que se realicen ediciones en una entrega o si te interesa proporcionar estadísticas a los profesores sobre el progreso de sus estudiantes:

Python

En nuestro ejemplo proporcionado, esta es una continuación del método load_activity_attachment anterior.

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

Por último, recupera la información del archivo adjunto de nuestra base de datos y entrega un formulario de entrada. El formulario de nuestro ejemplo proporcionado consta de un campo de entrada de cadena y un botón para enviar. Muestra la imagen del lugar de interés y pídele al estudiante que ingrese su nombre. Una vez que proporcione una respuesta, regístrala en nuestra base de datos.

Python

En nuestro ejemplo proporcionado, esta es una continuación del método load_activity_attachment anterior.

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

Para diferenciar a los usuarios, considera inhabilitar la función de enviar y, en su lugar, mostrar la respuesta correcta en la vista del profesor.

Agrega una ruta para el iframe de revisión de trabajos de los estudiantes

Por último, agrega una ruta para entregar el iframe de Student Work Review. El nombre de esta ruta debe coincidir con el que se proporcionó para studentWorkReviewUri cuando se crea un archivo adjunto. Esta ruta se abre cuando el profesor ve la entrega del alumno en la IU del calificador de Classroom.

Recibirás el parámetro de consulta submissionId cuando Classroom abre el iframe de Revisión de trabajos de los estudiantes. Úsala para recuperar el trabajo del alumno de tu base de datos local:

Python

En nuestro ejemplo, se encuentra en el archivo 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)

Prueba el complemento

Repite los pasos para probar el complemento de la explicación anterior. Debes tener un archivo adjunto que el estudiante pueda abrir.

Para probar el archivo adjunto de la actividad, completa los siguientes pasos:

  • Accede a Google Classroom como uno de tus usuarios de prueba de alumno en la misma clase que el usuario de prueba de profesor.
  • Navega a la pestaña Trabajo en clase y expande la Tarea de la prueba.
  • Haz clic en la tarjeta de adjunto del complemento para abrir la vista para estudiantes y enviar una respuesta a la actividad.
  • Cierra el iframe después de completar la actividad. De manera opcional, haz clic en el botón Turn In.

No deberías ver ningún cambio en Classroom después de completar la actividad. Ahora prueba el iframe de Student Work Review:

  • Accede a Classroom como el usuario de prueba de profesor.
  • Busca la columna de la tarea de prueba en la pestaña Calificaciones. Haz clic en el nombre de la tarea de prueba.
  • Busca la tarjeta del usuario de prueba del estudiante. Haz clic en el archivo adjunto de la tarjeta.

Confirma que aparezca la entrega correcta del estudiante.

¡Felicitaciones! Ya puedes continuar con el siguiente paso: sincronizar las calificaciones de los archivos adjuntos.