Đây là hướng dẫn thứ năm trong loạt hướng dẫn về các tiện ích bổ sung của Lớp học.
Trong hướng dẫn này, bạn sẽ sửa đổi ví dụ từ bước hướng dẫn trước đó để tạo tệp đính kèm loại hoạt động. Đây là mọi tệp đính kèm mà học viên phải gửi, chẳng hạn như câu trả lời bằng văn bản, bài kiểm tra hoặc sản phẩm khác do học viên tạo.
Bạn cần phân biệt giữa tệp đính kèm loại nội dung và loại hoạt động. Tệp đính kèm thuộc loại hoạt động khác với tệp đính kèm thuộc loại nội dung ở những điểm sau:
- Nút "Gửi bài" sẽ xuất hiện ở trên cùng bên phải của khung hiển thị Chế độ xem của học viên.
- Mã nhận dạng này cung cấp một giá trị nhận dạng duy nhất cho bài tập của học viên.
- Thẻ tệp đính kèm của họ sẽ xuất hiện trong giao diện người dùng của người chấm điểm trong Lớp học.
- Họ có thể đặt điểm cho bài tập mà họ thuộc về.
Hãy xem hướng dẫn tiếp theo để thảo luận về việc chấm điểm. Trong quá trình hướng dẫn này, bạn sẽ hoàn thành các bước sau:
- Sửa đổi các yêu cầu tạo tệp đính kèm trước đó thành API Lớp học để tạo tệp đính kèm thuộc loại hoạt động.
- Triển khai bộ nhớ liên tục cho bài nộp của học viên.
- Sửa đổi tuyến Chế độ xem của học viên trước đó để chấp nhận dữ liệu đầu vào của học viên.
- Cung cấp một tuyến để phân phát iframe Bài tập của học viên.
Sau khi hoàn tất, bạn có thể tạo tệp đính kèm thuộc loại hoạt động trên bài tập thông qua giao diện người dùng Google Lớp học khi đăng nhập với tư cách là giáo viên. Học viên trong lớp cũng có thể hoàn thành hoạt động trong iframe và gửi câu trả lời. Giáo viên có thể xem bài nộp của học viên trong giao diện người dùng chấm điểm của Lớp học.
Đối với mục đích của ví dụ này, hãy sử dụng lại mẫu tệp đính kèm trong hướng dẫn trước đó. Mẫu này hiển thị hình ảnh một địa danh nổi tiếng và chú thích có tên của địa danh đó. Hoạt động này bao gồm việc nhắc học viên cung cấp tên của địa danh.
Chỉnh sửa yêu cầu tạo tệp đính kèm
Chuyển đến phần mã mà bạn đã tạo tệp đính kèm thuộc loại nội dung trong hướng dẫn trước. Mục chính ở đây là một thực thể của đối tượng AddOnAttachment, trong đó chúng ta đã chỉ định teacherViewUri
, studentViewUri
và title
cho tệp đính kèm.
Mặc dù tất cả tệp đính kèm của tiện ích bổ sung đều yêu cầu 3 trường này, nhưng việc có hay không có studentWorkReviewUri
sẽ xác định xem tệp đính kèm đó là loại hoạt động hay loại nội dung. Yêu cầu CREATE
có studentWorkReviewUri
đã điền sẵn sẽ trở thành tệp đính kèm loại hoạt động, trong khi yêu cầu CREATE
không có studentWorkReviewUri
sẽ trở thành tệp đính kèm loại nội dung.
Việc duy nhất cần làm đối với yêu cầu này là điền vào trường studentWorkReviewUri
. Thêm một tuyến đường có tên phù hợp tại đây; bạn sẽ triển khai tuyến đường đó ở bước sau.
Python
Trong ví dụ mà chúng tôi cung cấp, mã này nằm trong phương thức create_attachments
trong tệp 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}",
}
Thêm bộ nhớ cố định cho tệp đính kèm thuộc loại nội dung
Ghi lại phản hồi của học viên đối với hoạt động của chúng ta. Bạn có thể xem lại sau khi giáo viên xem bài nộp trong khung hiển thị nội dung đánh giá bài tập của học viên.
Thiết lập giản đồ cơ sở dữ liệu cho Submission
. Ví dụ mà chúng tôi cung cấp yêu cầu học viên nhập tên của địa danh xuất hiện trong hình ảnh. Do đó, Submission
chứa các thuộc tính sau:
attachment_id
: Giá trị nhận dạng duy nhất của tệp đính kèm. Do Classroom chỉ định và được trả về trong phản hồi khi tạo tệp đính kèm.submission_id
: Giá trị nhận dạng cho bài nộp của học viên. Do Lớp học chỉ định và được trả về trong phản hồigetAddOnContext
trong Chế độ xem của học viên.
student_response
: Câu trả lời do học viên cung cấp.
Python
Mở rộng hoạt động triển khai SQLite và flask_sqlalchemy
từ các bước trước.
Chuyển đến tệp mà bạn đã xác định các bảng trước đó (models.py
nếu bạn đang làm theo ví dụ mà chúng tôi cung cấp). Thêm nội dung sau vào cuối tệp.
# 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))
Nhập lớp Submission
mới vào tệp máy chủ bằng các tuyến xử lý tệp đính kèm.
Sửa đổi tuyến Chế độ xem của học viên
Tiếp theo, hãy sửa đổi tuyến Chế độ xem của học viên trước đó để hiển thị một biểu mẫu nhỏ và chấp nhận dữ liệu đầu vào của học viên. Bạn có thể sử dụng lại hầu hết mã từ hướng dẫn trước.
Tìm mã máy chủ cung cấp tuyến đường cho Chế độ xem của học viên. Đây là tuyến được chỉ định trong trường studentViewUri
khi tạo tệp đính kèm.
Thay đổi đầu tiên cần thực hiện là trích xuất submissionId
từ phản hồi getAddOnContext
.
Python
Trong ví dụ mà chúng tôi cung cấp, mã này nằm trong phương thức load_activity_attachment
trong tệp 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")
Bạn cũng nên đưa ra yêu cầu để biết trạng thái bài nộp của học viên.
Phản hồi chứa giá trị SubmissionState
, cho biết các trạng thái như học viên đã mở tệp đính kèm hay đã nộp tệp đính kèm. Điều này có thể hữu ích nếu bạn muốn không cho phép chỉnh sửa bài nộp đã nộp hoặc nếu bạn muốn cung cấp cho giáo viên thông tin chi tiết về tiến trình của học viên:
Python
Trong ví dụ mà chúng tôi cung cấp, đây là phần tiếp theo của phương thức load_activity_attachment
ở trên.
# 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()
Cuối cùng, hãy tìm nạp thông tin về tệp đính kèm từ cơ sở dữ liệu của chúng tôi và phân phát một biểu mẫu nhập. Biểu mẫu trong ví dụ mà chúng tôi cung cấp bao gồm một trường nhập chuỗi và một nút gửi. Hiển thị hình ảnh địa danh và nhắc học viên nhập tên của địa danh đó. Sau khi họ đưa ra câu trả lời, hãy ghi lại câu trả lời đó trong cơ sở dữ liệu của chúng tôi.
Python
Trong ví dụ mà chúng tôi cung cấp, đây là phần tiếp theo của phương thức load_activity_attachment
ở trên.
# 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)
Để phân biệt giữa các người dùng, hãy cân nhắc tắt hàm gửi và hiển thị câu trả lời chính xác trong Chế độ xem của giáo viên.
Thêm tuyến cho iframe Bài tập của học viên
Cuối cùng, hãy thêm một tuyến để phân phát iframe Bài đánh giá bài tập của học viên. Tên của tuyến này phải khớp với tên được cung cấp cho studentWorkReviewUri
khi tạo tệp đính kèm. Tuyến này sẽ mở ra khi giáo viên xem bài nộp của học viên trong giao diện người dùng của người chấm điểm trong Lớp học.
Bạn sẽ nhận được thông số truy vấn submissionId
khi Lớp học mở iframe Bài làm của học viên. Sử dụng mã này để truy xuất bài tập của học viên từ cơ sở dữ liệu cục bộ:
Python
Trong ví dụ mà chúng tôi cung cấp, mã này nằm trong tệp 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)
Kiểm thử tiện ích bổ sung
Lặp lại Các bước kiểm thử tiện ích bổ sung trong hướng dẫn trước. Bạn phải có một tệp đính kèm mà học viên có thể mở.
Hoàn thành các bước sau để kiểm thử tệp đính kèm hoạt động:
- Đăng nhập vào Google Lớp học với vai trò là một trong những người dùng thử nghiệm học viên trong cùng lớp học với người dùng thử nghiệm giáo viên.
- Chuyển đến thẻ Bài tập trên lớp rồi mở rộng Bài tập kiểm tra.
- Nhấp vào thẻ tệp đính kèm của tiện ích bổ sung để mở Chế độ xem của học viên và gửi phản hồi cho hoạt động.
- Đóng iframe sau khi hoàn tất hoạt động. Bạn có thể nhấp vào nút Gửi.
Bạn sẽ không thấy gì thay đổi trong Lớp học sau khi hoàn thành hoạt động. Bây giờ, hãy kiểm thử iframe Bài tập của học viên:
- Đăng nhập vào Lớp học bằng vai trò người dùng thử nghiệm giáo viên.
- Tìm cột cho bài kiểm tra của bạn trong thẻ Điểm. Nhấp vào tên bài tập kiểm tra.
- Tìm thẻ của người dùng học viên thử nghiệm. Nhấp vào tệp đính kèm trên thẻ.
Xác nhận rằng bài nộp của học viên là bài nộp chính xác.
Xin chúc mừng! Bạn có thể chuyển sang bước tiếp theo: đồng bộ hoá điểm của tệp đính kèm.