Esta es la sexta explicación en los complementos de Classroom .
En esta explicación, modificarás el ejemplo del paso de explicación anterior. para producir un archivo adjunto calificado de tipo de actividad. También le pasas una calificación. en Google Classroom programáticamente, que aparece en la calificación del profesor libro como borrador de calificación.
Esta explicación difiere un poco de otras de la serie en que hay presentar dos posibles enfoques para volver a pasar las calificaciones en Classroom. Ambos tienen distintos impactos en el desarrollador y el usuario experiencias; ten en cuenta ambos cuando diseñes tu complemento de Classroom. Lee nuestra página de la guía Interacción con archivos adjuntos para obtener más información sobre las opciones de implementación.
Ten en cuenta que las funciones de calificación en la API son opcionales. Se pueden usar con cualquier archivo adjunto de tipo de actividad
En esta explicación, completaste lo siguiente:
- Modifica las solicitudes anteriores de creación de archivos adjuntos al La API de Classroom también permite establecer el denominador de calificación de los archivos adjuntos.
- Calificar de forma programática la entrega del estudiante y configurar los archivos adjuntos numerador de calificaciones.
- Implementa dos enfoques para pasar la calificación de la entrega a Classroom con credenciales de profesor en las que se accedió o no a la cuenta
Cuando termines, las calificaciones aparecerán en el libro de calificaciones de Classroom después de de devolución. El momento exacto en el que esto ocurre depende el enfoque de implementación.
A los efectos de este ejemplo, reutiliza la actividad del paso anterior. instructivo, en el que a un alumno se le muestra la imagen de un punto de referencia famoso y se le para ingresar su nombre. Asigna calificaciones completas en el archivo adjunto si el estudiante ingresa el nombre correcto; de lo contrario, escribe cero.
Comprender la función de calificación de la API de complementos de Classroom
Tu complemento puede establecer el numerador de calificaciones y el denominador de las calificaciones para un
adjunto. Se establecen respectivamente con pointsEarned
y maxPoints
.
en la API. Se muestra una tarjeta de archivos adjuntos en la IU de Classroom
el valor maxPoints
cuando se haya establecido.
Figura 1: La IU para crear tareas con tres tarjetas complementarias adjuntas que
tienen configurado maxPoints
.
La API de complementos de Classroom te permite establecer y configurar la configuración
Es la puntuación obtenida para las calificaciones de archivos adjuntos. No son lo mismo que el
assignment. Sin embargo, la configuración de las calificaciones de las tareas sigue las
configuración de calificación de los archivos adjuntos del archivo adjunto que tiene activada la etiqueta Sincronización de calificaciones
a su tarjeta de archivos adjuntos. Cuando aparezca la opción “Sincronización de calificaciones” el archivo adjunto establece pointsEarned
para un
la entrega de un estudiante, también definirá la calificación preliminar del estudiante para la tarea.
Por lo general, es el primer archivo adjunto que se agregó a la tarea que establece
maxPoints
recibe la “Sincronización de calificaciones” etiqueta. Consulta la IU de creación de tareas
de la Figura 1 para un ejemplo de la “Sincronización de calificaciones” etiqueta. Ten en cuenta que
el "Archivo adjunto 1" la tarjeta tiene el mensaje “Sincronización de calificaciones” etiqueta y que la calificación de la tarea
en el cuadro rojo se actualizó a 50 puntos. También ten en cuenta que,
aunque en la Figura 1
muestra tres tarjetas de archivos adjuntos, solo una de ellas tiene la opción “Sincronización de calificaciones” etiqueta. Este es
una limitación clave de la implementación actual: solo un archivo adjunto puede tener
la “Sincronización de calificaciones” etiqueta.
Si hay varios archivos adjuntos que tienen configurado maxPoints
, al quitar el elemento
archivo adjunto con “Sincronización de calificaciones” no habilita la “Sincronización de calificaciones” en cualquiera de los
archivos adjuntos restantes. Agregar otro archivo adjunto que establezca maxPoints
habilita
Se sincroniza la calificación en el nuevo archivo adjunto, y la calificación máxima de la tarea se ajusta a
la coincidencia. No existe un mecanismo para ver de forma programática qué archivo adjunto tiene el elemento
“Sincronización de calificaciones” ni consultar cuántos archivos adjuntos tiene una tarea en particular.
Cómo establecer la calificación máxima de un archivo adjunto
En esta sección, se describe cómo configurar el denominador de una calificación de archivo adjunto. que
es la puntuación máxima posible que todos los estudiantes pueden obtener en sus
los envíos de datos. Para hacerlo, configura el valor maxPoints
del adjunto.
Solo se necesita una pequeña modificación de nuestra implementación existente para habilitar
las funciones de calificación. Cuando crees un archivo adjunto, agrega el valor maxPoints
en
el mismo objeto AddOnAttachment
que contiene el studentWorkReviewUri
,
teacherViewUri
y otros campos de archivos adjuntos.
Ten en cuenta que la puntuación máxima predeterminada para una tarea nueva es 100. Sugerimos
configurando maxPoints
en un valor distinto de 100 para que puedas verificar que el valor
las calificaciones se establezcan correctamente. Establece maxPoints
en 50 como demostración:
Python
Agrega el campo maxPoints
cuando construyas el objeto attachment
, solo
antes de emitir una solicitud de CREATE
a la
Extremo courses.courseWork.addOnAttachments
. Puedes encontrarlo en la
webapp/attachment_routes.py
si se sigue el ejemplo proporcionado.
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.
"studentWorkReviewUri": {
"uri":
flask.url_for(
"view_submission", _scheme='https', _external=True)
},
# Sets the maximum points that a student can earn for this activity.
# This is the denominator in a fractional representation of a grade.
"maxPoints": 50,
# The title of the attachment.
"title": f"Attachment {attachment_count}",
}
A los fines de esta demostración, también almacenarás el valor maxPoints
en
tu base de datos local de adjuntos; Esto evita tener que hacer una llamada a la API adicional
cuando califiques las entregas de los estudiantes. Sin embargo, ten en cuenta que es posible que
los profesores modifican la configuración de calificaciones de las tareas independientemente del complemento. Enviar
una solicitud GET
al extremo courses.courseWork
para ver el
valor maxPoints
a nivel de la tarea. Cuando lo hagas, pasa el itemId
en el
CourseWork.id
.
Ahora actualiza tu modelo de base de datos para que también contenga el valor maxPoints
del adjunto.
Recomendamos usar el valor maxPoints
de la respuesta CREATE
:
Python
Primero, agrega un campo max_points
a la tabla Attachment
. Puede encontrar esta
en el archivo webapp/models.py
si sigues el ejemplo proporcionado.
# Database model to represent an attachment.
class Attachment(db.Model):
# The attachmentId is the unique identifier for the attachment.
attachment_id = db.Column(db.String(120), primary_key=True)
# The image filename to store.
image_filename = db.Column(db.String(120))
# The image caption to store.
image_caption = db.Column(db.String(120))
# The maximum number of points for this activity.
max_points = db.Column(db.Integer)
Vuelve a la solicitud courses.courseWork.addOnAttachments
CREATE
. Tienda
El valor de maxPoints
que se muestra en la respuesta
new_attachment = Attachment(
# The new attachment's unique ID, returned in the CREATE response.
attachment_id=resp.get("id"),
image_filename=key,
image_caption=value,
# Store the maxPoints value returned in the response.
max_points=int(resp.get("maxPoints")))
db.session.add(new_attachment)
db.session.commit()
El archivo adjunto ahora tiene una calificación máxima. Deberías poder probar este comportamiento ahora; agregas un archivo adjunto a una tarea nueva y observa que la tarjeta se muestra la página de “Sincronización de calificaciones” etiqueta y los "Puntos" de la tarea los cambios de valor.
Cómo configurar la calificación de entrega de un estudiante en Classroom
En esta sección, se describe cómo configurar el numerador para la calificación de un archivo adjunto. es decir,
la puntuación de un estudiante individual para el archivo adjunto. Para ello, establece un rol de estudiante
valor pointsEarned
de la entrega.
Ahora tienes que tomar una decisión importante: ¿cómo debería emitirse tu complemento
solicitar configurar pointsEarned
?
El problema es que la configuración de pointsEarned
requiere el permiso de OAuth teacher
.
No debes otorgar el permiso teacher
a usuarios estudiantes. esto podría provocar
comportamiento inesperado cuando los estudiantes interactúan con tu complemento, como cargar el
El iframe de la vista del profesor en lugar del iframe de la vista del alumno. Por lo tanto, tienes dos
Opciones para configurar pointsEarned
:
- Usar las credenciales del profesor que accedió
- Usar credenciales de profesor almacenadas (sin conexión)
En las siguientes secciones, se analizan las compensaciones de cada enfoque demostrando cada implementación. Ten en cuenta que los ejemplos que brindamos demuestran ambos enfoques para pasar una calificación a Classroom consulta la instrucciones específicas para cada lenguaje a continuación para ver cómo seleccionar un enfoque cuando ejecutando los ejemplos proporcionados:
Python
Busca la declaración SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS
en la parte superior.
de webapp/attachment_routes.py
archivo. Establece este valor en True
para transferir.
calificaciones con las credenciales del profesor que accedió. Establece este valor en False
para pasar las calificaciones con las credenciales almacenadas cuando el estudiante entregue el
actividad.
Establece calificaciones con las credenciales del profesor que accedió.
Usa las credenciales del usuario que accedió a fin de emitir la solicitud para configurar pointsEarned
.
Esto debería parecer bastante intuitivo, ya que refleja el resto de la implementación.
hasta ahora y su realización requiere poco esfuerzo.
Sin embargo, ten en cuenta que el profesor solo interactúa con los archivos en el iframe de revisión del trabajo de los estudiantes. Esto tiene algunos aspectos importantes implicaciones:
- No se propagarán calificaciones en Classroom hasta que el profesor tome la decisión. acción en la IU de Classroom.
- Es posible que el profesor tenga que abrir todas las entregas de los estudiantes para completar calificaciones de los estudiantes.
- Hay una breve demora entre Classroom que recibe la calificación y su apariencia en la IU de Classroom. El retraso es de 5 a 10 segundos, pero hasta 30 segundos.
La combinación de estos factores implica que los profesores podrían tener que hacer y requiere un trabajo manual considerable para completar por completo las calificaciones de una clase.
Para implementar este enfoque, agrega una llamada a la API adicional a la cuenta de estudiante existente. Ruta de revisión del trabajo.
Después de recuperar los registros de entregas y archivos adjuntos del estudiante, evalúa el
la entrega de un estudiante y almacenar la calificación resultante. Establece la calificación en la
Campo pointsEarned
de un objeto AddOnAttachmentStudentSubmission
. Finalmente,
enviar una solicitud PATCH
al
Extremo courses.courseWork.addOnAttachments.studentSubmissions
con el
Instancia de AddOnAttachmentStudentSubmission
en el cuerpo de la solicitud. Ten en cuenta que
también debes especificar pointsEarned
en el updateMask
de nuestra solicitud PATCH
:
Python
# 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)
grade = 0
# See if the student response matches the stored name.
if student_submission.student_response.lower(
) == attachment.image_caption.lower():
grade = attachment.max_points
# Create an instance of the Classroom service.
classroom_service = ch._credential_handler.get_classroom_service()
# Build an AddOnAttachmentStudentSubmission instance.
add_on_attachment_student_submission = {
# Specifies the student's score for this attachment.
"pointsEarned": grade,
}
# Issue a PATCH request to set the grade numerator for this attachment.
patch_grade_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
courseId=flask.session["courseId"],
itemId=flask.session["itemId"],
attachmentId=flask.session["attachmentId"],
submissionId=flask.session["submissionId"],
# updateMask is a list of fields being modified.
updateMask="pointsEarned",
body=add_on_attachment_student_submission).execute()
Establece calificaciones con credenciales de profesores sin conexión
El segundo enfoque para establecer calificaciones requiere el uso de credenciales almacenadas.
para el profesor que creó el archivo adjunto. Esta implementación requiere que
construyes credenciales con la actualización de un profesor autorizado previamente y
tokens de acceso y, luego, usa estas credenciales para configurar pointsEarned
.
Una ventaja fundamental de este enfoque es que las calificaciones se completan sin requerir las acciones de los profesores en la IU de Classroom, lo que evita los problemas. mencionados anteriormente. El resultado es que los usuarios finales perciben la experiencia de calificación. como fluida y eficiente. Además, este enfoque te permite elegir la momento en el que pasas las calificaciones, como cuando los estudiantes completan la actividad o de forma asíncrona.
Para implementar este enfoque, completa las siguientes tareas:
- Modificar los registros de la base de datos de usuarios para almacenar un token de acceso
- Modifica los registros de la base de datos de archivos adjuntos para almacenar un ID de profesor.
- Recuperar las credenciales de los profesores y, de forma opcional, crear una nueva Instancia de servicio de Classroom.
- Configura la calificación de una entrega.
A los efectos de esta demostración, establecer la calificación cuando el estudiante complete la encuesta la actividad; es decir, cuando el estudiante envía el formulario en la vista de estudiante ruta.
Modificar los registros de la base de datos del usuario para almacenar el token de acceso
Se requieren dos tokens únicos para realizar llamadas a la API: el token de actualización y el
token de acceso. Si has seguido la serie de explicaciones hasta ahora, tu
El esquema de la tabla User
ya debe almacenar un token de actualización. Almacena la actualización
token es suficiente cuando solo haces llamadas a la API con el usuario que accedió, ya que
recibes un token de acceso como parte del flujo de autenticación.
Sin embargo, ahora debes hacer
llamadas como usuario que no accedió
lo que significa que el flujo de autenticación no está disponible. Por lo tanto, debes almacenar
el token de acceso junto con el token de actualización. Actualiza el esquema de tu tabla User
a
incluye un token de acceso:
Python
En el ejemplo que proporcionamos, se encuentra en el archivo webapp/models.py
.
# Database model to represent a user.
class User(db.Model):
# The user's identifying information:
id = db.Column(db.String(120), primary_key=True)
display_name = db.Column(db.String(80))
email = db.Column(db.String(120), unique=True)
portrait_url = db.Column(db.Text())
# The user's refresh token, which will be used to obtain an access token.
# Note that refresh tokens will become invalid if:
# - The refresh token has not been used for six months.
# - The user revokes your app's access permissions.
# - The user changes passwords.
# - The user belongs to a Google Cloud organization
# that has session control policies in effect.
refresh_token = db.Column(db.Text())
# An access token for this user.
access_token = db.Column(db.Text())
Luego, actualiza cualquier código que cree o actualice un registro User
para almacenar también el
token de acceso:
Python
En el ejemplo que proporcionamos, se encuentra en el archivo webapp/credential_handler.py
.
def save_credentials_to_storage(self, credentials):
# Issue a request for the user's profile details.
user_info_service = googleapiclient.discovery.build(
serviceName="oauth2", version="v2", credentials=credentials)
user_info = user_info_service.userinfo().get().execute()
flask.session["username"] = user_info.get("name")
flask.session["login_hint"] = user_info.get("id")
# See if we have any stored credentials for this user. If they have used
# the add-on before, we should have received login_hint in the query
# parameters.
existing_user = self.get_credentials_from_storage(user_info.get("id"))
# If we do have stored credentials, update the database.
if existing_user:
if user_info:
existing_user.id = user_info.get("id")
existing_user.display_name = user_info.get("name")
existing_user.email = user_info.get("email")
existing_user.portrait_url = user_info.get("picture")
if credentials and credentials.refresh_token is not None:
existing_user.refresh_token = credentials.refresh_token
# Update the access token.
existing_user.access_token = credentials.token
# If not, this must be a new user, so add a new entry to the database.
else:
new_user = User(
id=user_info.get("id"),
display_name=user_info.get("name"),
email=user_info.get("email"),
portrait_url=user_info.get("picture"),
refresh_token=credentials.refresh_token,
# Store the access token as well.
access_token=credentials.token)
db.session.add(new_user)
db.session.commit()
Modifica los registros de la base de datos de archivos adjuntos para almacenar un ID de profesor
Si deseas configurar la calificación de una actividad, realiza una llamada para establecer pointsEarned
como un valor
profesor del curso. Existen varias formas de hacerlo:
- Almacenar una asignación local de credenciales de profesores a IDs de cursos Sin embargo, ten en cuenta un mismo profesor no siempre se asocie con un curso en particular.
- Emitir
GET
solicitudes al extremocourses
de la API de Classroom para buscar a los profesores actuales. Luego, consulta los registros de usuarios locales para ubicar que coincidan con tus credenciales de profesor. - Cuando crees un archivo adjunto de complemento, almacena un ID de profesor en el archivo
de la base de datos de adjuntos. Luego, recupera las credenciales de profesor del
Se pasan
attachmentId
al iframe de vista de alumno.
Este ejemplo demuestra la última opción, ya que estás estableciendo calificaciones cuando la estudiante completa un archivo adjunto de actividad.
Agrega un campo de ID de profesor a la tabla Attachment
de tu base de datos:
Python
En el ejemplo que proporcionamos, se encuentra en el archivo webapp/models.py
.
# Database model to represent an attachment.
class Attachment(db.Model):
# The attachmentId is the unique identifier for the attachment.
attachment_id = db.Column(db.String(120), primary_key=True)
# The image filename to store.
image_filename = db.Column(db.String(120))
# The image caption to store.
image_caption = db.Column(db.String(120))
# The maximum number of points for this activity.
max_points = db.Column(db.Integer)
# The ID of the teacher that created the attachment.
teacher_id = db.Column(db.String(120))
Luego, actualiza cualquier código que cree o actualice un registro Attachment
para que también
almacenar el ID del creador:
Python
En nuestro ejemplo proporcionado, esto se encuentra en el método create_attachments
de la
webapp/attachment_routes.py
archivo.
# Store the attachment by id.
new_attachment = Attachment(
# The new attachment's unique ID, returned in the CREATE response.
attachment_id=resp.get("id"),
image_filename=key,
image_caption=value,
max_points=int(resp.get("maxPoints")),
teacher_id=flask.session["login_hint"])
db.session.add(new_attachment)
db.session.commit()
Recuperar las credenciales de los profesores
Busca la ruta que entrega el iframe de la vista del alumno. Inmediatamente después de almacenar la respuesta del estudiante en tu base de datos local, recuperar el archivo credenciales de tu almacenamiento local. Esto debería ser sencillo, dada la preparación en los dos pasos anteriores. También puedes usarlos para construir un nuevo instancia del servicio de Classroom para el usuario profesor:
Python
En el ejemplo que proporcionamos, esto se encuentra en el método load_activity_attachment
de
el archivo webapp/attachment_routes.py
.
# Create an instance of the Classroom service using the tokens for the
# teacher that created the attachment.
# We're assuming that there are already credentials in the session, which
# should be true given that we are adding this within the Student View
# route; we must have had valid credentials for the student to reach this
# point. The student credentials will be valid to construct a Classroom
# service for another user except for the tokens.
if not flask.session.get("credentials"):
raise ValueError(
"No credentials found in session for the requested user.")
# Make a copy of the student credentials so we don't modify the original.
teacher_credentials_dict = deepcopy(flask.session.get("credentials"))
# Retrieve the requested user's stored record.
teacher_record = User.query.get(attachment.teacher_id)
# Apply the user's tokens to the copied credentials.
teacher_credentials_dict["refresh_token"] = teacher_record.refresh_token
teacher_credentials_dict["token"] = teacher_record.access_token
# Construct a temporary credentials object.
teacher_credentials = google.oauth2.credentials.Credentials(
**teacher_credentials_dict)
# Refresh the credentials if necessary; we don't know when this teacher last
# made a call.
if teacher_credentials.expired:
teacher_credentials.refresh(Request())
# Request the Classroom service for the specified user.
teacher_classroom_service = googleapiclient.discovery.build(
serviceName=CLASSROOM_API_SERVICE_NAME,
version=CLASSROOM_API_VERSION,
credentials=teacher_credentials)
Cómo configurar la calificación de una entrega
A partir de ahora, el procedimiento es idéntico al de usar la interfaz del profesor credenciales. Sin embargo, ten en cuenta que debes hacer la llamada con el profesor. credenciales recuperadas en el paso anterior:
Python
# Issue a PATCH request as the teacher to set the grade numerator for this
# attachment.
patch_grade_response = teacher_classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
courseId=flask.session["courseId"],
itemId=flask.session["itemId"],
attachmentId=flask.session["attachmentId"],
submissionId=flask.session["submissionId"],
# updateMask is a list of fields being modified.
updateMask="pointsEarned",
body=add_on_attachment_student_submission).execute()
Prueba el complemento
Al igual que en la explicación anterior, crea una tarea con un tipo de actividad. archivo adjunto como profesor, enviar una respuesta como estudiante, y luego abrir su en el iframe de revisión del trabajo de los estudiantes. Deberías poder ver aparecerán en diferentes momentos según el enfoque de implementación:
- Si elegiste pasar una calificación cuando el estudiante completó la actividad, ya deberías ver la calificación preliminar en la IU antes de abrir el iframe de revisión del trabajo de los alumnos También puedes verlo en la lista de estudiantes cuando abriendo la tarea y, en la sección "Calificación", junto al cuadro de diálogo Trabajo del estudiante Revisa el iframe.
- Si eliges pasar una calificación cuando el profesor abre el Trabajo del alumno Revisa el iframe; la calificación debe aparecer en la sección "Calificación" poco después del se carga el iframe. Como se mencionó anteriormente, este proceso puede tardar hasta 30 segundos. Luego, la calificación del alumno específico debería aparecer en la otras vistas del libro de calificaciones de Classroom.
Confirma que se muestre la puntuación correcta para el estudiante.
¡Felicitaciones! Ya puedes continuar con el siguiente paso: crear archivos adjuntos fuera de Google Classroom.