Este é o quinto tutorial da série de tutoriais dos complementos do Google Sala de Aula.
Neste tutorial, você vai modificar o exemplo da etapa anterior para produzir um anexo do tipo de atividade. São todos os anexos que exigem uma entrega do estudante, como uma resposta por escrito, um teste ou outro artefato gerado pelo estudante.
É importante distinguir entre anexos de conteúdo e de atividade. Os anexos do tipo "Atividade" diferem dos anexos do tipo "Conteúdo" das seguintes maneiras:
- Um botão "Enviar" aparece no canto superior direito do iframe da visualização do estudante.
- Eles fornecem um identificador exclusivo para o trabalho do estudante.
- O cartão de anexo aparece na interface da ferramenta de notas do Google Sala de Aula.
- Eles podem definir uma nota para a atividade a que pertencem.
Consulte o próximo tutorial para saber mais sobre a avaliação. Durante este tutorial, você vai concluir o seguinte:
- Modifique as solicitações de criação de anexos anteriores para a API Classroom para criar um anexo do tipo atividade.
- Implemente o armazenamento permanente para envios dos estudantes.
- Modifique a rota anterior da visualização do estudante para aceitar a entrada do estudante.
- Forneça uma rota para exibir o iframe de revisão do trabalho do estudante.
Depois de terminar, você poderá criar anexos de atividades nas atividades na interface do Google Sala de Aula quando estiver conectado como professor. Os estudantes da turma também podem concluir a atividade no iframe e enviar uma resposta. O professor pode ver o envio do estudante na interface de avaliação do Google Sala de Aula.
Para este exemplo, reutilize o modelo de anexo do tutorial anterior, que mostra uma imagem de um ponto turístico famoso e uma legenda com o nome dele. A atividade consiste em pedir ao estudante para informar o nome do ponto de referência.
Modificar a solicitação de criação de anexo
Navegue até a seção do código em que você criou um anexo de tipo de conteúdo
no tutorial anterior. O item principal aqui é uma instância de um
objeto AddOnAttachment, em que especificamos anteriormente teacherViewUri
,
studentViewUri
e title
para o anexo.
Embora todos os anexos de complementos exijam esses três campos, a presença ou
ausência de um studentWorkReviewUri
determina se o anexo é
do tipo atividade ou conteúdo. Uma solicitação CREATE
com um studentWorkReviewUri
preenchido se torna um anexo do tipo "atividade", enquanto uma solicitação CREATE
sem um studentWorkReviewUri
se torna um anexo do tipo "conteúdo".
A única modificação a ser feita nessa solicitação é preencher o campo studentWorkReviewUri
. Adicione uma rota com o nome adequado aqui. Você
vai implementá-la em uma etapa posterior.
Python
No exemplo fornecido, isso está no método create_attachments
no
arquivo 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}",
}
Adicionar armazenamento permanente para anexos de tipo de conteúdo
Grave a resposta do estudante à nossa atividade. Você pode consultar o trabalho mais tarde, quando o professor acessar o envio no iframe de análise do trabalho do estudante.
Configurar um esquema de banco de dados para um Submission
. O exemplo fornecido espera que os estudantes insiram o nome do ponto de referência mostrado em uma imagem. Um Submission
contém os seguintes atributos:
attachment_id
: um identificador exclusivo de um anexo. Atribuído pelo Classroom e retornado na resposta ao criar um anexo.submission_id
: um identificador para um envio do estudante. Atribuída pelo Google Sala de Aula e retornada na respostagetAddOnContext
na visualização do estudante.
student_response
: a resposta fornecida pelo estudante.
Python
Estenda a implementação do SQLite e do flask_sqlalchemy
das etapas anteriores.
Navegue até o arquivo em que você definiu as tabelas anteriores
(models.py
se você estiver seguindo nosso exemplo). Adicione o seguinte na
parte de baixo do arquivo.
# 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))
Importe a nova classe Submission
para o arquivo do servidor com suas rotas de processamento de anexos.
Modificar a rota da prévia do estudante
Em seguida, modifique a rota anterior da visualização do estudante para mostrar um pequeno formulário e aceitar entradas do estudante. Você pode reutilizar a maior parte do código do tutorial anterior.
Localize o código do servidor que fornece a rota para a visualização de estudante. Essa é
a rota especificada no campo studentViewUri
ao criar um anexo.
A primeira mudança a ser feita é extrair o submissionId
da
resposta getAddOnContext
.
Python
No exemplo fornecido, isso está no método load_activity_attachment
no
arquivo 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")
Você também pode emitir uma solicitação para saber o status do envio do estudante.
A resposta contém um valor SubmissionState
, que indica estados,
como se o estudante abriu o anexo ou o enviou. Isso pode ser
útil se você quiser proibir edições em um envio entregue ou se quiser
fornecer insights aos professores sobre o progresso dos estudantes:
Python
No exemplo fornecido, essa é uma continuação do
método load_activity_attachment
acima.
# 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 fim, busque as informações do anexo no nosso banco de dados e exiba um formulário de entrada. O formulário no exemplo fornecido consiste em um campo de entrada de string e um botão de envio. Mostre a imagem do ponto de referência e peça para o estudante digitar o nome dele. Quando eles responderem, registre a resposta no nosso banco de dados.
Python
No exemplo fornecido, essa é uma continuação do
método load_activity_attachment
acima.
# 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 os usuários, desative a função de envio e mostre a resposta correta na visualização do professor.
Adicionar uma rota para o iframe de avaliação do trabalho do estudante
Por fim, adicione uma rota para exibir o iframe de avaliação do trabalho do estudante. O nome dessa
rota precisa corresponder ao fornecido para o studentWorkReviewUri
ao criar
um anexo. Essa rota é aberta quando o professor visualiza o envio do estudante na
interface do Google Sala de Aula.
Você recebe o parâmetro de consulta submissionId
quando o Google Sala de Aula
abre o iframe de análise do trabalho do estudante. Use-o para recuperar o trabalho do estudante do
seu banco de dados local:
Python
No exemplo fornecido, isso está no arquivo 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)
Testar o complemento
Repita as etapas de teste do complemento do tutorial anterior. Você precisa ter um anexo que possa ser aberto pelo estudante.
Siga estas etapas para testar o anexo da atividade:
- Faça login no Google Sala de Aula como um dos usuários de teste aluno na mesma turma que o usuário de teste do professor.
- Navegue até a guia Atividades e abra a Atividade do teste.
- Clique no card de anexo do complemento para abrir a visualização do estudante e enviar uma resposta para a atividade.
- Feche o iframe depois de concluir a atividade. Se preferir, clique no botão Turn In.
Nada vai mudar no Google Sala de Aula depois de concluir a atividade. Agora teste o iframe de avaliação do trabalho do estudante:
- Faça login no Google Sala de Aula como o usuário de teste professor.
- Encontre a coluna da sua atividade de teste na guia Notas. Clique no nome da atividade de teste.
- Encontre o card do usuário estudante de teste. Clique no anexo no card.
Confirme se o envio correto aparece para o estudante.
Parabéns! Você está pronto para passar para a próxima etapa: sincronizar as notas de anexos.