這是 Classroom 外掛程式的第 6 個逐步操作說明 這一系列的影片
在本逐步操作說明中,您將修改上一個逐步操作說明步驟中的範例 來產生「已評分」的活動類型附件。此外,您還可發還成績 透過程式新增至 Google Classroom 。
這個逐步操作說明與本系列其他影片稍有不同 提出兩種可能將成績發還給學生的方法 Classroom。兩者對開發人員和使用者都有不同影響 服務;在您設計 Classroom 外掛程式時,請同時考量兩者。 參閱與附件互動指南網頁,進一步瞭解 實作選項
請注意,API 的評分功能為選用項目。這類模型適用於 任何活動類型附件。
在本逐步操作說明中,您將完成下列步驟:
- 將先前的附件建立要求修改為 Classroom API 也會同時設定附件的成績分母。
- 透過程式為學生繳交的作業評分,並設定附件的 。
- 採用兩種方法,將繳交成績傳送給 使用老師登入或離線使用的憑證 Classroom。
完成後,成績就會顯示在 Classroom 成績單中, 觸發回傳式曝光行為確切時機取決於 。
為了達成此例,請重複使用上一個 其中一位學生看到某知名地標的圖片, 。為學生指派完整成績 會輸入正確名稱,否則會輸入 0。
瞭解 Classroom 外掛程式 API 評分功能
您的外掛程式可以同時設定
附件。這些項目分別使用 pointsEarned
和 maxPoints
設定
也就是 API 中的值。Classroom UI 中顯示附件資訊卡
maxPoints
值 (如果已設定的話)。
圖 1. 指派作業的使用者介面,內含三張外掛程式附件卡,
已設定「maxPoints
」。
Classroom 外掛程式 API 可讓您配置設定
因附件成績而獲得的分數。這兩者不同
作業成績。不過,作業成績設定會沿用
開啟「成績同步處理」標籤的附件附件成績設定
附件資訊卡「成績同步處理」功能連結設定 pointsEarned
的
學生繳交的作業,也會設定學生的作業暫定成績。
通常是該作業新增到作業的第一個附件
maxPoints
收到「成績同步處理」通知標籤。查看指派作業的 UI
圖 1 中的「成績同步處理」範例標籤。請注意,
「附件 1」資訊卡上會顯示「成績同步處理」功能和作業成績
紅框中的點數已更新為 50 分另外請注意,雖然圖 1
顯示三張附件資訊卡,只有一張資訊卡有「成績同步處理」功能標籤。這是
目前實作的一項重要限制:只有一個附件可含有
「成績同步處理」標籤。
如果有多個附件設定了 maxPoints
,請移除
含有「成績同步處理」的附件「不會」啟用「成績同步處理」功能任何
其他附件。新增另一個設定 maxPoints
的附件
新附件的成績同步處理功能,作業成績上限會隨之調整
比對。系統沒有透過程式化的方式,查看哪些附件具有
「成績同步處理」標籤,或查看特定作業內含的附件數量。
設定附件的最高成績
本節說明如何設定附件成績的「分母」;並
是所有學生在學習成果方面的最高分數
提交內容。方法是設定連結的 maxPoints
值。
只需稍微修改現有的導入設定,即可
評分功能建立連結時,請將 maxPoints
值加入
包含 studentWorkReviewUri
的相同 AddOnAttachment
物件,
teacherViewUri
和其他附件欄位。
請注意,新作業的預設最高分數是 100 分。建議做法
將 maxPoints
設為 100 以外的值,這樣您就能確認
成績設定正確將 maxPoints
設為 50 做為示範:
Python
請在建構 attachment
物件時新增 maxPoints
欄位,
再向CREATE
courses.courseWork.addOnAttachments
端點。您可以在
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.
"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}",
}
為方便示範,請將 maxPoints
值儲存在
本機附件資料庫這樣就不必再發出額外的 API 呼叫
以便日後為學生繳交的作業評分但請注意,
老師會獨立變更作業成績設定,不受外掛程式影響。傳送
向 courses.courseWork
端點發出 GET
要求,查看
指派層級的 maxPoints
值。執行時,請將 itemId
傳入
「CourseWork.id
」欄位中的值。
現在請更新資料庫模型,讓它一併保存連結的 maxPoints
值。
建議您使用 CREATE
回應中的 maxPoints
值:
Python
首先,在 Attachment
資料表中新增 max_points
欄位。您可以
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)
返回 courses.courseWork.addOnAttachments
CREATE
要求。商店
回應中傳回的 maxPoints
值。
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()
附件的成績已達上限。您應該可以測試這種行為 現在;在新作業中加入附件,您會發現附件資訊卡 會顯示「成績同步處理」標籤和作業的「分數」值的變化。
在 Classroom 中設定學生繳交成績
本節說明如何為附件成績設定「分子」;這是
個別學生附件的分數。如要設定,請設定學生
提交內容的 pointsEarned
值。
您現在有重要決定:您的外掛程式該如何
要求設定「pointsEarned
」?
問題在於設定 pointsEarned
需要 teacher
OAuth 範圍。
請勿授予學生使用者「teacher
」範圍的權限。這可能會導致
當學生與您的外掛程式互動時,例如載入
是使用老師檢視畫面 iframe,而非學生檢視畫面 iframe。因此,您在預測期間
pointsEarned
設定方式:
- 使用老師已登入的憑證。
- 使用已儲存的 (離線) 老師憑證。
以下各節將討論這兩種方法的優缺點 這些操作會示範各項導入作業請注意,我們提供的範例 分別將成績傳送至 Classroom;請參閱 請參閱以下特定語言的操作說明,瞭解如何在 範例:
Python
找到頂端的 SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS
宣告
(共 webapp/attachment_routes.py
個檔案)。將這個值設為 True
即可回傳
使用老師登入的憑證分數。將這個值設為 False
以便在學生繳交
活動。
使用老師登入的憑證設定成績
使用已登入的使用者憑證發出要求來設定 pointsEarned
。
這看起來應該要相當直覺,因為能夠反映其他實作內容
到目前為止,還不需要太多心力。
不過,考量到老師「只會」與學生的學習互動 學生作業檢閱 iframe 中的提交內容。這點很重要 影響:
- 老師尚未在 Classroom 中填入成績 。
- 教師可能需要開啟所有學生繳交的作業,才能填入所有學生的資料 學生成績。
- Classroom 收到成績之間會有短暫延遲 以及 UI 的外觀。誤點為 通常是 5 到 10 秒,但最長可達 30 秒。
老師在綜合這些因素後必須 要完整填入課程成績,相當耗時的人工作業。
如要實作這個方法,請為現有學生另外新增一個 API 呼叫 工作回顧路線。
擷取學生繳交的作業和附件記錄後,請評估
並儲存學生的提交的成績。在
AddOnAttachmentStudentSubmission
物件的 pointsEarned
欄位。最後
發出 PATCH
要求給
courses.courseWork.addOnAttachments.studentSubmissions
端點,其中包含
AddOnAttachmentStudentSubmission
例項。請注意
您也必須在 PATCH
要求的 updateMask
中指定 pointsEarned
:
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()
使用老師離線憑證設定成績
設定成績的第二種方法必須使用「已儲存的憑證」
建立附件的老師名稱要進行這項導入作業,
您需使用先前授權老師的重新整理和
存取權杖,然後使用這些憑證設定 pointsEarned
。
這種做法的一大優點是,可以直接填入成績,而不必要求 老師在 Classroom UI 中執行動作,可避免發生問題 請參閱上述說明。這會導致使用者感受到評分體驗 以及流暢又有效率的平台此外,這個做法可讓您選擇 但等您傳回成績的時間點,例如學生完成 活動或非同步
請完成下列工作來實作此方法:
- 修改使用者資料庫記錄,以儲存存取權杖。
- 修改附件資料庫記錄以儲存老師 ID。
- 擷取老師的憑證,並視需要建構一個新的 Classroom 服務執行個體。
- 設定作業的成績。
為了進行示範,請在學生完成時設定成績 活動;所以當學生透過「學生檢視畫面」提交表單時 路徑。
修改使用者資料庫記錄,儲存存取權杖
若要進行 API 呼叫,您必須具備兩個專屬符記:更新憑證和
存取權杖。如果您到目前為止已經觀看過逐步教學系列課程
User
資料表結構定義應該已經儲存更新權杖。儲存重新整理
只搭配已登入的使用者進行 API 呼叫時,就足以提供儲存空間,
您會在驗證流程中收到存取權杖。
不過,您現在必須透過已登入的使用者以外的身分撥打電話。
這表示驗證流程無法使用因此,您需要儲存
以及存取權杖將「User
」資料表結構定義更新為
加入存取權杖:
Python
在提供的範例中,它位於 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())
接著更新任何建立或更新 User
記錄的程式碼,以便儲存
存取權杖:
Python
在提供的範例中,它位於 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()
修改附件資料庫記錄來儲存老師 ID
如要為活動設定成績,請呼叫以將 pointsEarned
設為
本課程稍後將說明以下提供幾種方法:
- 儲存老師憑證和課程 ID 的本機對應。但請注意 一位老師不一定每次都會與特定課程建立關聯。
- 向 Classroom API
courses
端點發出GET
要求,以便: 取得目前的老師資訊。接著,查詢本機使用者記錄來找出 對應的老師憑證。 - 建立外掛程式附件時,請將老師 ID 儲存在本機
連結資料庫再從
attachmentId
已傳遞至學生檢視畫面 iframe。
本例是最後一個選項,因為您要在 學生完成活動附件。
將老師 ID 欄位新增至資料庫的 Attachment
資料表:
Python
在提供的範例中,它位於 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))
然後更新任何會建立或更新 Attachment
記錄的程式碼,以便一併
儲存創作者的 ID:
Python
在上述範例中,這是 create_attachments
方法的
webapp/attachment_routes.py
檔案。
# 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()
擷取老師的憑證
找出提供學生檢視畫面 iframe 的路徑。儲存後立即 取得學生的回覆,並擷取老師的 擷取來自本機儲存空間的憑證這應該十分簡單,因為 前兩個步驟做準備您也可以利用這些 Pod 老師使用者的 Classroom 服務範例:
Python
在上述範例中,這是 load_activity_attachment
方法中的
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)
設定繳交作業的成績
在這裡的程序與使用已登入老師 憑證。但請注意,您應與老師通話 擷取的憑證:
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()
測試外掛程式
與上一個逐步操作說明類似,請建立具有活動類型的作業 以學生身分提交回應,然後開啟 學生作業檢閱 iframe 中的提交內容。您應該會看到 成績的顯示方式會因導入方法而異:
- 如果您在學生完成活動後選擇發還成績, 您應該已經在 UI 中看到作業的暫定成績,然後再開啟 學生作業回顧 iframe。您也可以在 開啟作業,然後在「成績」頁面勾選「學生作業」旁邊的方塊 查看 iframe。
- 如果您在老師開啟學生作業時選擇發還成績 評論 iframe,成績應會顯示在「成績」中。方塊內 iframe 載入。如上文所述,這項作業最多可能需要 30 秒才能完成。 之後,「特定學生」的成績也會顯示在 其他 Classroom 成績單檢視畫面。
確認學生看到的分數正確無誤。
恭喜!若要進行下一個步驟:建立附件 。