这是 Google 课堂插件演示系列中的第五个演示。
在本演示中,您将修改上一个演示步骤中的示例以生成 activity 类型附件。这类附件是指需要学生提交的任何附件,例如书面回复、测验或其他学生生成的工件。
区分内容类型和活动类型附件非常重要。 活动类型附件与内容类型附件的不同之处如下:
- 在学生视图 iframe 的右上角,会显示“上交”按钮。
- 并为学生的作业提供唯一标识符。
- 他们的附件卡片会显示在 Google 课堂评分者界面中。
- 他们可以为所属的作业设置成绩。
请参阅下一篇演示,了解有关评分的讨论。在本演示中,您需要完成以下操作:
- 修改之前发送到 Classroom API 的附件创建请求,以创建活动类型的附件。
- 为学生提交的作业实现永久性存储。
- 修改之前的“学生视图”路由以接受学生输入的内容。
- 提供传送学生作业评价 iframe 的路径。
完成后,您可以在以教师身份登录时,通过 Google 课堂界面在作业中创建活动型附件。班级中的学生也可以在 iframe 中完成活动并提交回复。教师可以在 Google 课堂的评分界面中查看学生提交的作业。
在本示例中,请重复使用上一个演示中的附件模板,该模板显示了著名地标的图片以及包含地标名称的图片说明。此 activity 包括提示学生提供地标的名称。
修改附件创建请求
前往您在上一演示中创建内容类型附件的代码部分。此处的关键项是 AddOnAttachment 对象的实例,我们之前在该实例中指定了附件的 teacherViewUri
、studentViewUri
和 title
。
虽然所有插件附件都需要这三个字段,但 studentWorkReviewUri
的存在决定了附件是活动类型还是内容类型。包含已填充 studentWorkReviewUri
的 CREATE
请求会成为 activity 类型附件,而不含 studentWorkReviewUri
的 CREATE
请求则会成为内容类型附件。
对此请求所做的唯一修改是填充 studentWorkReviewUri
字段。在此处添加适当命名的路由;您将在后续步骤中实现该路由。
Python
在我们提供的示例中,它就位于 webapp/attachment_routes.py
文件的 create_attachments
方法中。
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}",
}
为内容类型附件添加永久性存储空间
记录学生对我们活动的回答。您可以稍后查询,当教师在“学生的作业”评价 iframe 中查看提交内容时。
为 Submission
设置数据库架构。我们提供的示例要求学生输入图片中显示的地标的名称。因此,Submission
包含以下属性:
attachment_id
:连接的唯一标识符。由 Google 课堂分配,并在创建附件时在响应中返回。submission_id
:学生提交的标识符。由 Google 课堂分配,并在学生视图的getAddOnContext
回复中返回。
student_response
:学生提供的答案。
Python
扩展前面步骤中的 SQLite 和 flask_sqlalchemy
实现。
导航到您在其中定义了上述表的文件(如果遵循我们提供的示例,则转到 models.py
)。在文件底部添加以下代码。
# 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))
将新的 Submission
类连同附件处理路由一起导入到服务器文件中。
修改“学生视图”路由
接下来,修改之前的“Student View”路线,以显示一个小表单并接受学生的输入。您可以重复使用上一个演示中的大部分代码。
找到提供学生视图路线的服务器代码。这是创建连接时在 studentViewUri
字段中指定的路由。要进行的第一项更改是从 getAddOnContext
响应中提取 submissionId
。
Python
在我们提供的示例中,它就位于 webapp/attachment_routes.py
文件的 load_activity_attachment
方法中。
# 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")
您也可以请求获取学生提交状态。
响应包含 SubmissionState
值,用于指示状态,例如学生是否已打开附件或上交附件。如果您想禁止对上交的提交内容进行修改,或者您希望向教师提供有关学生学生进度的数据分析,上述做法会非常有用:
Python
在我们提供的示例中,这是对上述 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()
最后,从我们的数据库获取附件信息并提供输入表单。我们所提供示例中的表单由一个字符串输入字段和一个提交按钮组成。显示地标图片,并提示学生输入课程名称。 他们给出回复后,请将其记录在我们的数据库中。
Python
在我们提供的示例中,这是对上述 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)
为了区分用户,不妨考虑停用提交功能,改为在教师视图中显示正确答案。
为学生作业回顾 iframe 添加路线
最后,添加用于传送学生作业评价 iframe 的路径。此路由的名称应与创建连接时为 studentWorkReviewUri
提供的名称一致。当教师在 Google 课堂评分工具界面中查看学生提交的作业时,系统会打开此路由。
当 Google 课堂打开学生作业评价 iframe 时,您会收到 submissionId
查询参数。您可以使用它从本地数据库中检索学生的作业:
Python
在我们提供的示例中,它位于 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)
测试插件
重复测试上一演示中的插件步骤。您应该有一个学生可以打开的附件。
如需测试 activity 连接,请完成以下步骤:
- 以与教师测试用户相同的课程中的某一学生测试用户的身份登录 Google 课堂。
- 导航至课业标签页,然后展开测试作业。
- 点击插件附件卡片以打开“学生视图”,然后提交该活动的回答。
- 完成活动后关闭 iframe。(可选)点击上交按钮。
完成活动后,Google 课堂中应该不会出现任何变化。现在,测试学生作业回顾 iframe:
- 以教师测试用户的身份登录“课堂”。
- 在成绩标签页中找到测试作业对应的列。点击测试作业的名称。
- 找到测试学生用户的卡片。点击卡片上的附件。
确认系统显示该学生提交的正确作业。
恭喜!您已准备好继续执行下一步:同步附件成绩。