Tệp đính kèm loại nội dung

Đây là hướng dẫn từng bước thứ tư trong các tiện ích bổ sung cho Google Lớp học loạt video hướng dẫn từng bước.

Trong hướng dẫn này, bạn sẽ tương tác với API Google Lớp học để tạo tệp đính kèm. Bạn cung cấp các tuyến để người dùng xem nội dung tệp đính kèm. Chiến lược phát hành đĩa đơn còn tuỳ thuộc vào vai trò của người dùng trong lớp. Hướng dẫn từng bước này bao gồm tệp đính kèm dạng nội dung, không yêu cầu học viên gửi.

Trong hướng dẫn từng bước này, bạn sẽ hoàn thành các bước sau:

  • Truy xuất và sử dụng các tham số truy vấn của tiện ích bổ sung sau đây:
    • addOnToken: Mã thông báo uỷ quyền đã được chuyển vào tính năng Khám phá tệp đính kèm Chế độ xem.
    • itemId: Giá trị nhận dạng duy nhất cho CourseWork, CourseWorkMaterial hoặc Thông báo nhận được tệp đính kèm tiện ích bổ sung.
    • itemType: "courseWork", "courseWorkMaterials" hoặc "thông báo".
    • courseId: Giá trị nhận dạng duy nhất của khoá học trên Google Lớp học trong mà hệ thống sẽ tạo bài tập.
    • attachmentId: Giá trị nhận dạng duy nhất do Google Lớp học chỉ định cho một tệp đính kèm bằng tiện ích bổ sung sau khi tạo.
  • Triển khai bộ nhớ liên tục cho các tệp đính kèm loại nội dung.
  • Cung cấp các tuyến để tạo tệp đính kèm và phân phát Chế độ xem dành cho giáo viên và iframe Chế độ xem của học viên.
  • Gửi các yêu cầu sau đây tới API tiện ích bổ sung của Google Lớp học:
    • Tạo tệp đính kèm mới.
    • Lấy ngữ cảnh tiện ích bổ sung, xác định xem người dùng đã đăng nhập có phải là học sinh hoặc giáo viên.

Sau khi hoàn tất, bạn có thể tạo tệp đính kèm dạng nội dung trên bài tập thông qua giao diện người dùng của Google Lớp học khi đăng nhập với tư cách là giáo viên. Giáo viên và học viên ở lớp cũng có thể xem nội dung.

Bật API lớp học

Thực hiện các lệnh gọi đến API Lớp học bắt đầu từ bước này. API phải cho dự án Google Cloud của bạn trước khi bạn có thể gọi đến dự án đó. Tìm đường chuyển đến mục thư viện của API Google Lớp học rồi chọn Bật.

Xử lý tham số truy vấn của Chế độ xem khám phá tệp đính kèm

Như đã thảo luận trước đó, Google Lớp học truyền các tham số truy vấn khi đang tải Chế độ xem khám phá tệp đính kèm trong iframe:

  • courseId: Mã của khoá học hiện tại trên Lớp học.
  • itemId: Giá trị nhận dạng duy nhất cho CourseWork, CourseWorkMaterial hoặc Thông báo nhận được tệp đính kèm tiện ích bổ sung.
  • itemType: "courseWork", "courseWorkMaterials" hoặc "thông báo".
  • addOnToken: Mã thông báo dùng để cho phép một số Các thao tác đối với tiện ích bổ sung dành cho Lớp học.
  • login_hint: Mã nhận dạng trên Google của người dùng hiện tại.

Hướng dẫn này sẽ đề cập đến courseId, itemId, itemTypeaddOnToken. Giữ lại và truyền các mã này khi thực hiện lệnh gọi đến API Lớp học.

Như trong bước hướng dẫn từng bước trước đó, hãy lưu trữ các giá trị tham số truy vấn đã chuyển trong trong buổi trò chuyện của chúng tôi. Điều quan trọng là chúng ta phải thực hiện việc này khi Chế độ xem khám phá tệp đính kèm là mở lần đầu tiên, vì đây là cơ hội duy nhất để Lớp học truyền các tham số truy vấn này.

Python

Chuyển đến tệp máy chủ Flask cung cấp tuyến đường cho Tệp đính kèm Chế độ xem khám phá (attachment-discovery-routes.py nếu bạn đang theo dõi ví dụ). Ở đầu tuyến trang đích bổ sung của bạn (/classroom-addon trong ví dụ được cung cấp của chúng tôi), truy xuất và lưu trữ Tham số truy vấn courseId, itemId, itemTypeaddOnToken.

# Retrieve the itemId, courseId, and addOnToken query parameters.
if flask.request.args.get("itemId"):
    flask.session["itemId"] = flask.request.args.get("itemId")
if flask.request.args.get("itemType"):
    flask.session["itemType"] = flask.request.args.get("itemType")
if flask.request.args.get("courseId"):
    flask.session["courseId"] = flask.request.args.get("courseId")
if flask.request.args.get("addOnToken"):
    flask.session["addOnToken"] = flask.request.args.get("addOnToken")

Chỉ ghi các giá trị này vào phiên hoạt động khi có các giá trị đó; chúng không đã được truyền lại nếu người dùng quay lại Chế độ xem khám phá tệp đính kèm mà không đóng iframe.

Thêm bộ nhớ cố định cho các tệp đính kèm dạng nội dung

Bạn cần có bản ghi cục bộ của mọi tệp đính kèm đã tạo. Nhờ đó, bạn có thể tra cứu nội dung mà giáo viên đã chọn bằng giá trị nhận dạng do Lớp học.

Thiết lập giản đồ cơ sở dữ liệu cho Attachment. Sau đây là ví dụ mà chúng tôi cung cấp các tệp đính kèm hiển thị hình ảnh và chú thích. Attachment chứa phương thức các thuộc tính sau:

  • attachment_id: Giá trị nhận dạng duy nhất của một tệp đính kèm. Người giao Lớp học và được trả về trong phản hồi khi tạo một tệp đính kèm.
  • image_filename: Tên tệp cục bộ của hình ảnh cần hiển thị.
  • image_caption: Chú thích hiển thị cùng với hình ảnh.

Python

Mở rộng quy trình 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 bảng Người dùng (models.py nếu bạn đang làm theo ví dụ được cung cấp của chúng tôi). Thêm thông tin sau vào dưới cùng của tệp bên dưới lớp User.

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))

Nhập lớp Tệp đính kèm mới vào tệp máy chủ cùng với tệp đính kèm của bạn xử lý các tuyến đường.

Thiết lập tuyến đường mới

Bắt đầu bước hướng dẫn này bằng cách thiết lập một số trang mới trong ứng dụng của chúng tôi. Những tiện ích này cho phép người dùng tạo và xem nội dung thông qua tiện ích bổ sung của chúng tôi.

Thêm tuyến đường tạo tệp đính kèm

Bạn cần có các trang để giáo viên chọn nội dung và tạo tệp đính kèm về vấn đề yêu cầu. Triển khai tuyến /attachment-options để hiển thị các lựa chọn nội dung để giáo viên chọn. Bạn cũng cần có các mẫu để chọn nội dung và tạo trang xác nhận. Ví dụ mà chúng tôi cung cấp có chứa các mẫu dành cho các trường hợp này, đồng thời cũng có thể hiển thị các yêu cầu và phản hồi từ API lớp học.

Lưu ý rằng bạn có thể sửa đổi Chế độ xem khám phá tệp đính kèm hiện có trang đích để hiển thị các lựa chọn nội dung thay vì tạo /attachment-options. Chúng tôi khuyên bạn nên tạo một trang mới để bài tập này để bạn duy trì hành vi SSO được triển khai trong giây hướng dẫn từng bước, chẳng hạn như thu hồi quyền cho ứng dụng. Những điều này cần chứng minh hữu ích khi bạn tạo và thử nghiệm tiện ích bổ sung.

Giáo viên có thể chọn trong số một tập hợp nhỏ các hình ảnh có chú thích trong ví dụ: Chúng tôi đã cung cấp bốn hình ảnh về các địa danh nổi tiếng có chú thích là bắt nguồn từ tên tệp.

Python

Trong ví dụ đã cung cấp, chúng nằm trong tệp webapp/attachment_routes.py.

@app.route("/attachment-options", methods=["GET", "POST"])
def attachment_options():
    """
    Render the attachment options page from the "attachment-options.html"
    template.

    This page displays a grid of images that the user can select using
    checkboxes.
    """

    # A list of the filenames in the static/images directory.
    image_filenames = os.listdir(os.path.join(app.static_folder, "images"))

    # The image_list_form_builder method creates a form that displays a grid
    # of images, checkboxes, and captions with a Submit button. All images
    # passed in image_filenames will be shown, and the captions will be the
    # title-cased filenames.

    # The form must be built dynamically due to limitations in WTForms. The
    # image_list_form_builder method therefore also returns a list of
    # attribute names in the form, which will be used by the HTML template
    # to properly render the form.
    form, var_names = image_list_form_builder(image_filenames)

    # If the form was submitted, validate the input and create the attachments.
    if form.validate_on_submit():

        # Build a dictionary that maps image filenames to captions.
        # There will be one dictionary entry per selected item in the form.
        filename_caption_pairs = construct_filename_caption_dictionary_list(
            form)

        # Check that the user selected at least one image, then proceed to
        # make requests to the Classroom API.
        if len(filename_caption_pairs) > 0:
            return create_attachments(filename_caption_pairs)
        else:
            return flask.render_template(
                "create-attachment.html",
                message="You didn't select any images.",
                form=form,
                var_names=var_names)

    return flask.render_template(
        "attachment-options.html",
        message=("You've reached the attachment options page. "
                "Select one or more images and click 'Create Attachment'."),
        form=form,
        var_names=var_names,
    )

Thao tác này sẽ tạo ra lệnh "Tạo tệp đính kèm" có dạng như sau:

Khung hiển thị lựa chọn nội dung mẫu Python

Giáo viên có thể chọn nhiều hình ảnh. Tạo một tệp đính kèm cho mỗi hình ảnh mà giáo viên đã chọn trong phương thức create_attachments.

Vấn đề về yêu cầu tạo tệp đính kèm

Bây giờ, bạn đã biết giáo viên muốn đính kèm phần nội dung nào, gửi yêu cầu tới API Lớp học để tạo tệp đính kèm trên bài tập. Lưu trữ thông tin chi tiết về tệp đính kèm trong cơ sở dữ liệu của bạn sau khi nhận được phản hồi từ API Lớp học.

Bắt đầu bằng cách tải một bản sao của dịch vụ Lớp học:

Python

Trong ví dụ đã cung cấp, chúng nằm trong tệp webapp/attachment_routes.py.

def create_attachments(filename_caption_pairs):
    """
    Create attachments and show an acknowledgement page.

    Args:
        filename_caption_pairs: A dictionary that maps image filenames to
            captions.
    """
    # Get the Google Classroom service.
    classroom_service = googleapiclient.discovery.build(
        serviceName="classroom",
        version="v1",
        credentials=credentials)

Gửi yêu cầu CREATE cho courses.courseWork.addOnAttachments điểm cuối. Đối với mỗi hình ảnh giáo viên chọn, trước tiên, hãy tạo một Đối tượng AddOnAttachment:

Python

Trong ví dụ chúng tôi cung cấp, đây là phần tiếp theo của create_attachments .

# Create a new attachment for each image that was selected.
attachment_count = 0
for key, value in filename_caption_pairs.items():
    attachment_count += 1

    # Create a dictionary with values for the AddOnAttachment object fields.
    attachment = {
        # Specifies the route for a teacher user.
        "teacherViewUri": {
            "uri":
                flask.url_for(
                    "load_content_attachment", _scheme='https', _external=True),
        },
        # Specifies the route for a student user.
        "studentViewUri": {
            "uri":
                flask.url_for(
                    "load_content_attachment", _scheme='https', _external=True)
        },
        # The title of the attachment.
        "title": f"Attachment {attachment_count}",
    }

Ít nhất các trường teacherViewUri, studentViewUrititle phải là cho mỗi tệp đính kèm. teacherViewUristudentViewUri biểu thị các URL được tải khi tệp đính kèm được mở bằng kiểu người dùng tương ứng.

Gửi đối tượng AddOnAttachment trong phần nội dung của yêu cầu đến bộ phận thích hợp điểm cuối addOnAttachments. Hãy cung cấp courseId, itemId, itemTypeaddOnToken giá trị nhận dạng với mỗi yêu cầu.

Python

Trong ví dụ chúng tôi cung cấp, đây là phần tiếp theo của create_attachments .

# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
    case "announcements":
        parent = classroom_service.courses().announcements()
    case "courseWorkMaterials":
        parent = classroom_service.courses().courseWorkMaterials()
    case _:
        parent = classroom_service.courses().courseWork()

# Issue a request to create the attachment.
resp = parent.addOnAttachments().create(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    addOnToken=flask.session["addOnToken"],
    body=attachment).execute()

Tạo một mục nhập cho tệp đính kèm này trong cơ sở dữ liệu cục bộ của bạn để bạn có thể sau này tải đúng nội dung. Lớp học trả về một giá trị id duy nhất trong phản hồi cho yêu cầu tạo, vì vậy hãy sử dụng khoá này làm khoá chính trong cơ sở dữ liệu. Ngoài ra, xin lưu ý rằng Lớp học truyền attachmentId khi mở Chế độ xem của giáo viên và học viên:

Python

Trong ví dụ chúng tôi cung cấp, đây là phần tiếp theo của create_attachments .

# Store the value 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)
db.session.add(new_attachment)
db.session.commit()

Hãy cân nhắc chuyển người dùng đến một trang xác nhận tại thời điểm này rằng họ đã tạo thành công tệp đính kèm.

Cho phép tệp đính kèm từ tiện ích bổ sung

Bây giờ là thời điểm thích hợp để thêm mọi địa chỉ thích hợp vào Tệp đính kèm được phép Trường tiền tố URI trong Cấu hình ứng dụng của SDK Google Workspace Marketplace . Tiện ích bổ sung của bạn chỉ có thể tạo tệp đính kèm từ một trong các tiền tố URI được liệt kê trên trang này. Đây là một biện pháp bảo mật nhằm giúp giảm khả năng tấn công xen giữa.

Cách đơn giản nhất là cung cấp tên miền cấp cao nhất của bạn trong trường này, cho ví dụ https://example.com. https://localhost:<your port number>/ sẽ hoạt động nếu bạn đang sử dụng máy cục bộ làm máy chủ web.

Thêm các tuyến cho Chế độ xem của giáo viên và học viên

Có 4 iframe mà tiện ích bổ sung Google Lớp học có thể được tải. Bạn chỉ tạo các tuyến phân phát iframe của Chế độ xem khám phá tệp đính kèm, do đó xa. Tiếp theo, hãy thêm các tuyến để phân phát iframe Chế độ xem của giáo viên và học viên.

iframe Chế độ xem của giáo viên là bắt buộc để hiển thị bản xem trước của học viên kinh nghiệm, nhưng có thể tuỳ ý cung cấp thông tin bổ sung hoặc nội dung chỉnh sửa các tính năng AI mới.

Chế độ xem của học viên là trang mà mỗi học viên nhìn thấy khi học viên mở trang tệp đính kèm bằng tiện ích bổ sung.

Trong bài tập này, hãy tạo một /load-content-attachment duy nhất cung cấp cho cả Chế độ xem của giáo viên và Học viên. Sử dụng API Lớp học để xác định xem người dùng là giáo viên hay học sinh khi trang tải.

Python

Trong ví dụ đã cung cấp, chúng nằm trong tệp webapp/attachment_routes.py.

@app.route("/load-content-attachment")
def load_content_attachment():
    """
    Load the attachment for the user's role."""

    # Since this is a landing page for the Teacher and Student View iframes, we
    # need to preserve the incoming query parameters.
    if flask.request.args.get("itemId"):
        flask.session["itemId"] = flask.request.args.get("itemId")
    if flask.request.args.get("itemType"):
        flask.session["itemType"] = flask.request.args.get("itemType")
    if flask.request.args.get("courseId"):
        flask.session["courseId"] = flask.request.args.get("courseId")
    if flask.request.args.get("attachmentId"):
        flask.session["attachmentId"] = flask.request.args.get("attachmentId")

Hãy lưu ý rằng bạn cũng nên xác thực người dùng tại thời điểm này. Bạn cũng sẽ xử lý tham số truy vấn login_hint tại đây và chuyển người dùng đến quy trình uỷ quyền của bạn nếu cần. Xem thông tin chi tiết về hướng dẫn đăng nhập đã thảo luận trong hướng dẫn từng bước trước để biết thêm thông tin về quy trình này.

Sau đó, gửi yêu cầu đến điểm cuối getAddOnContext khớp với mục đó loại.

Python

Trong ví dụ đã cung cấp, đây là phần tiếp theo của load_content_attachment.

# Create an instance of the Classroom service.
classroom_service = googleapiclient.discovery.build(
    serviceName="classroom"
    version="v1",
    credentials=credentials)

# Use the itemType to determine which stream item type the teacher created
match flask.session["itemType"]:
    case "announcements":
        parent = classroom_service.courses().announcements()
    case "courseWorkMaterials":
        parent = classroom_service.courses().courseWorkMaterials()
    case _:
        parent = classroom_service.courses().courseWork()

addon_context_response = parent.getAddOnContext(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"]).execute()

Phương thức này trả về thông tin về vai trò của người dùng hiện tại trong lớp. Thay đổi chế độ xem mà người dùng nhìn thấy tuỳ theo vai trò của họ. Chính xác một trong Các trường studentContext hoặc teacherContext được điền sẵn trong phản hồi . Hãy kiểm tra các vấn đề này để xác định cách tương tác với người dùng.

Trong mọi trường hợp, hãy sử dụng giá trị tham số truy vấn attachmentId để biết tệp đính kèm để truy xuất từ cơ sở dữ liệu của chúng tôi. Tham số truy vấn này được cung cấp khi mở URI Chế độ xem của giáo viên hoặc Chế độ xem của học viên.

Python

Trong ví dụ đã cung cấp, đây là phần tiếp theo của load_content_attachment.

# Determine which view we are in by testing the returned context type.
user_context = "student" if addon_context_response.get(
    "studentContext") else "teacher"

# Look up the attachment in the database.
attachment = Attachment.query.get(flask.session["attachmentId"])

# Set the text for the next page depending on the user's role.
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 enjoy this image of a famous landmark!")

# Show the content with the customized message text.
return flask.render_template(
    "show-content-attachment.html",
    message=message_str,
    image_filename=attachment.image_filename,
    image_caption=attachment.image_caption,
    responses=response_strings)

Kiểm thử tiện ích bổ sung

Hãy hoàn tất các bước sau để kiểm thử việc tạo tệp đính kèm:

  • Đăng nhập vào [Google Lớp học] bằng một trong Người dùng thử nghiệm do giáo viên cung cấp.
  • Chuyển đến thẻ Bài tập trên lớp và tạo một Bài tập mới.
  • Nhấp vào nút Tiện ích bổ sung bên dưới vùng văn bản, sau đó chọn tiện ích bổ sung của bạn. iframe mở ra và tiện ích bổ sung sẽ tải URI thiết lập tệp đính kèm mà bạn được chỉ định trên trang Cấu hình ứng dụng của SDK Google Workspace Marketplace.
  • Chọn một phần nội dung để đính kèm vào bài tập.
  • Đóng iframe sau khi quy trình tạo tệp đính kèm hoàn tất.

Bạn sẽ thấy một thẻ tệp đính kèm xuất hiện trong giao diện người dùng khi tạo bài tập trên Google Google Lớp học. Nhấp vào thẻ để mở iframe Chế độ xem dành cho giáo viên rồi xác nhận rằng tệp đính kèm chính xác xuất hiện. Nhấp vào nút Giao bài.

Hãy hoàn thành các bước sau để kiểm tra trải nghiệm của học viên:

  • Sau đó, đăng nhập vào Lớp học với tư cách là người dùng trong bài kiểm tra của học viên trên cùng với tư cách là giáo viên thử nghiệm người dùng.
  • Tìm bài tập kiểm tra trong thẻ Bài tập trên lớp.
  • Mở rộng bài tập rồi nhấp vào thẻ đính kèm để mở Chế độ xem của học viên iframe.

Kiểm tra để đảm bảo học viên xuất hiện đúng tệp đính kèm.

Xin chúc mừng! Bạn có thể chuyển sang bước tiếp theo: tạo tệp đính kèm loại hoạt động.