这是 Google 课堂插件演示系列的第 7 个演示。
在本演示中,您将向 Web 应用添加行为,以在 Google 课堂之外创建插件附件。使用此行为可让用户通过您的现有商品或网站创建插件附件。这对于 CourseWork
集成来说也是一个很好的补充,因为您可以将现有流量引导至您的插件提供的改进版用户体验,而无需更改其流程。如需了解建议的流程,请参阅在 Google 课堂之外创建附件指南页面。
您还可以为您的插件添加行为,以通过编程方式修改包含插件附件的作业。无论作业是谁创建的,只要其中包含您的某个插件附件,您都可以修改该作业。这对于学生在完成活动后上交作业特别有用,可向教师表明已完成分配的任务,并且学生的作业可以接受审核。
您可以扩展支持内容类型或 activity 类型附件的插件的最终版本。本指南中使用 content-type 附件。
添加作业管理 OAuth 范围
请确保您的应用请求以下范围:
https://www.googleapis.com/auth/classroom.addons.teacher
https://www.googleapis.com/auth/classroom.addons.student
https://www.googleapis.com/auth/classroom.coursework.students
之前不需要 classroom.coursework.students
作用域,它用于创建或修改 CourseWork
分配。将此范围添加到 Cloud 项目的 Google Workspace Marketplace SDK、OAuth 意见征求界面和服务器代码中的范围列表。
Python
SCOPES = [
"https://www.googleapis.com/auth/classroom.addons.teacher",
"https://www.googleapis.com/auth/classroom.addons.student",
"https://www.googleapis.com/auth/classroom.coursework.students",
]
在 Google 课堂中创建作业
向非 iframe 网页添加按钮
通过本演示中介绍的流程,用户可以通过非 Google 产品创建 Google 课堂作业和附件。实际上,这可能是您现有的网站或应用。在本例中,您需要创建一个模拟网页来充当外部网站。您需要一个按钮或链接,点击该按钮或链接后,系统会打开新路线,执行建议的 CourseWork
流程来创建新作业。
如果您尚未添加,还需要添加一个按钮或链接以允许用户登录。您将需要用户凭据才能发出后续 API 请求,因此他们必须完成 OAuth 2.0 握手。如需具体指导,请参阅登录演示。
Python
提供的 Python 示例会修改第一步演示中介绍的 /index
路线。
<!-- /webapp/templates/index.html -->
<a href="clear-credentials.html">Logout</a>
<a href="start-auth-flow.html">Login</a>
<br>
<a href="create-coursework-assignment.html">Create a CourseWork Assignment</a>
在您的网站中添加 HTML 模板来表示目的地。此页面将显示要附加到 CourseWork
作业的内容。
<!-- /webapp/templates/example-coursework-assignment.html -->
<h1>CourseWork assignment loaded!</h1>
<p>You've loaded a CourseWork assignment! It was created from an external web page.</p>
创建一个新的 Python 模块文件来处理与课程作业相关的路由。
这是我们提供的示例中的 coursework_routes.py
。添加以下三条路线;请注意,您稍后会填充其中的部分内容。
# /webapp/coursework_routes.py
@app.route("/create-coursework-assignment")
def create_coursework_assignment():
"""
Completes the assignment creation flow.
"""
# Check that the user is signed in. If not, perform the OAuth 2.0
# authorization flow.
credentials = get_credentials()
if not credentials:
return start_auth_flow("coursework_assignment_callback")
# Construct the Google Classroom service.
classroom_service = get_classroom_service()
pass # To be completed later.
@app.route("/example-coursework-assignment/<assignment_type>")
def example_coursework_assignment(assignment_type):
"""
Renders the "example-coursework-assignment.html" template.
"""
return flask.render_template(
"example-coursework-assignment.html", assignment_type=assignment_type
)
@app.route("/coursework-assignment-callback")
def coursework_assignment_callback():
"""
Completes the OAuth 2.0 handshake and stores credentials in the session.
This is identical to the callback introduced in the sign-in walkthrough,
but redirects the user to the index page instead of the attachment
discovery page.
"""
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE,
scopes=SCOPES,
state=flask.session["state"],
redirect_uri=flask.url_for("coursework_assignment_callback", _external=True),
)
flow.fetch_token(authorization_response=flask.request.url)
credentials = flow.credentials
flask.session["credentials"] = session_credentials_to_dict(
credentials
)
# Close the current window and redirect the user to the index page.
return flask.render_template("close-me.html", redirect_destination="index")
检查用户是否有权创建附件
用户必须满足几个前提条件,您才能代表他们创建插件附件。为方便起见,Google 提供了 userProfiles.checkUserCapability
方法来确定用户是否满足这些前提条件。满足这些前提条件的用户称为符合条件的用户。
向 CourseWork
创建路线实现添加了资格检查。
然后,测试响应中的 allowed
字段。对于符合条件的用户,请按照相应逻辑创建包含插件附件的作业。否则,请创建关联材料。您需要知道用户要创建作业的课程的 ID。通常,您会提示用户指定要使用的课程。为简单起见,我们在此示例中使用硬编码值。
Python
# /webapp/coursework_routes.py
@app.route("/create-coursework-assignment")
def create_coursework_assignment():
"""
Completes the assignment creation flow.
"""
# ... Check that the user is signed in and get the Classroom service ...
# Check whether the user can create add-on attachments.
eligibility_response = (
classroom_service.userProfiles()
.checkUserCapability(
userId="me",
capability="CREATE_ADD_ON_ATTACHMENT",
# The previewVersion is necessary while the method is available in the
# Workspace Developer Preview Program.
previewVersion="V1_20240930_PREVIEW",
).execute()
)
is_create_attachment_eligible = eligibility_response.get("allowed")
if is_create_attachment_eligible:
# See the "Create an assignment with add-on attachment for eligible users" section for implementation.
if not is_create_attachment_eligible:
# See the "Create a Link Material" section for implementation.
为符合条件的用户创建包含插件附件的作业
如果用户符合创建插件附件的条件,请执行以下操作:
- 发送 API 请求,在 Google 课堂中创建无附件的“
courseWork
”作业。 - 提取新创建的分配的
id
。 - 构造一个新的 CourseWork
AddOnAttachment
。 - 在 Google 课堂中针对新创建的作业发送请求,以创建插件附件。
Python
# The ID of the course to which the assignment will be added.
course_id = 1234567890 # TODO(developer) Replace with an actual course ID.
# /webapp/coursework_routes.py
if is_create_attachment_eligible:
# Create an assignment.
coursework = {
"title": "My CourseWork Assignment with Add-on Attachment",
"description": "Created using the Classroom CourseWork API.",
"workType": "ASSIGNMENT",
"state": "DRAFT", # Set to 'PUBLISHED' to assign to students.
}
# Issue a request to create the assignment.
create_assignment_response = (
classroom_service.courses()
.courseWork()
.create(courseId=course_id, body=coursework)
.execute()
)
# Create an add-on attachment that links to the selected content and
# associate it with the new assignment.
content_url = flask.url_for(
"example_coursework_assignment",
assignment_type="add-on-attachment",
_scheme="https",
_external=True,
)
# Construct an AddOnAttachment instance.
attachment = {
"teacherViewUri": {"uri": content_url},
"studentViewUri": {"uri": content_url},
"title": f'Test Attachment for Assignment {create_assignment_response.get("id")}',
}
# Issue a request to create the attachment.
add_on_attachment_response = (
classroom_service.courses()
.courseWork()
.addOnAttachments()
.create(
courseId=course_id,
itemId=create_assignment_response.get("id"), # ID of the new assignment.
body=attachment,
)
.execute()
)
创建关联材料
如果用户不符合创建插件附件的条件,请改为创建关联材料,具体方法如下:
Python
# The ID of the course to which the assignment will be added.
course_id = 1234567890 # TODO(developer) Replace with an actual course ID.
if not is_create_attachment_eligible:
coursework = {
"title": "My CourseWork Assignment with Link Material",
"description": "Created using the Classroom CourseWork API.",
"workType": "ASSIGNMENT",
"state": "DRAFT", # Set to 'PUBLISHED' to assign to students.
# Specify the URL for your content as a Link Material.
"materials": [
{
"link": {
"url": flask.url_for(
"example_coursework_assignment",
assignment_type="link-material",
_scheme="https",
_external=True,
)
}
}
],
}
# Issue a request to create the assignment.
assignment_response = (
classroom_service.courses()
.courseWork()
.create(courseId=course_id, body=coursework)
.execute()
)
修改已创建的作业
无论 Google 课堂信息流项目的创建者是谁,只要该项目包含至少一个您的插件附件,您都可以访问、修改、交出、重新声明或退回该项目。信息流项是指任何 Announcement
、CourseWork
作业或 CourseWorkMaterial
。
为了演示这一点,您将添加一个路由来修改给定的串流项。使用此方法可以验证您能否访问和修改您使用 API 创建的信息流内容以及教师通过 Google 课堂界面创建的信息流内容。
向本演示中首次修改的网页再添加一个链接或按钮。系统应该会打开一个新路线来修改 CourseWork
分配。
Python
提供的 Python 示例修改了本演示前面修改的 /index
路由。
<!-- /webapp/templates/index.html -->
<a href="modify-coursework-assignment.html">Create a CourseWork Assignment</a>
创建新路由来处理与 CourseWork 相关的路由。这在我们提供的示例的 coursework_routes.py
文件中。
# Check that the user is signed in.
credentials = get_credentials()
if not credentials:
return start_auth_flow("coursework_assignment_callback")
# Get the Google Classroom service.
classroom_service = get_classroom_service()
# The ID of the course to which the assignment will be added.
# Ordinarily, you'll prompt the user to specify which course to use. For
# simplicity, we use a hard-coded value in this example.
course_id = 1234567890 # TODO(developer) Replace with an actual course ID.
assignment_id = 1234567890 # TODO(developer) Replace with an actual assignment ID.
# Retrieve details about the CourseWork assignment.
get_coursework_response = (
classroom_service.courses()
.courseWork()
.get(courseId=course_id, id=assignment_id)
.execute()
)
# Alter the current title.
assignment_title = f"{get_coursework_response.get('title')} (Modified by API request)"
# Issue a request to modify the assignment.
modify_coursework_response = (
classroom_service.courses()
.courseWork()
.patch(
courseId=course_id,
id=assignment_id,
updateMask="title",
body={"title": assignment_title},
)
.execute()
)
测试插件
为简单起见,提供的示例使用硬编码的课程和作业标识符。您可以使用教师凭据向 courses
和 courseWork
资源的 get
和 list
方法发出请求,以获取这些标识符。创建 courseWork
作业时,系统也会在响应中返回这些 ID。
测试链接材料的创建
运行服务器,然后前往您的首页,并以未拥有 Google Workspace 教育版教与学或 Plus 版许可的教师用户身份登录。您可以从测试网域的管理控制台中切换用户的许可状态。点击创建课业作业按钮,然后打开 Google 课堂界面,验证是否已创建包含链接材料附件的作业。附件应显示链接网页的标题和网址
测试插件附件的创建
返回索引页面,然后以拥有 Google Workspace 教育版教与学或 Plus 版许可的教师用户身份登录。点击 Create a CourseWork Assignment(创建 CourseWork 作业)按钮,然后打开 Google 课堂界面并验证是否已创建带有插件附件的作业。附件应显示您的插件应用的名称和代码中指定的标题。
测试作业修改
返回索引页面,确保您以拥有教与学或 Plus 版许可的教师用户身份登录。点击修改课程作业按钮,然后返回 Google 课堂界面,验证作业标题是否已更改。
恭喜!您已完成演示系列。