Lampiran jenis konten

Ini adalah panduan keempat di add-on Classroom seri panduan kami.

Dalam panduan ini, Anda akan berinteraksi dengan Google Classroom API untuk membuat lampiran. Anda memberikan rute bagi pengguna untuk melihat konten lampiran. Tujuan tampilan berbeda bergantung pada peran pengguna di kelas. Panduan ini membahas lampiran jenis konten, yang tidak memerlukan kiriman siswa.

Dalam panduan ini, Anda akan menyelesaikan hal-hal berikut:

  • Ambil dan gunakan parameter kueri add-on berikut:
    • addOnToken: Token otorisasi yang diteruskan ke Penemuan Lampiran View.
    • itemId: ID unik untuk CourseWork, CourseWorkMaterial, atau Pengumuman yang menerima lampiran add-on.
    • itemType: "courseWork", "courseWorkMaterials" atau "pengumuman".
    • courseId: ID unik untuk kursus Google Classroom di yang tugasnya dibuat.
    • attachmentId: ID unik yang ditetapkan oleh Google Classroom ke lampiran add-on setelah dibuat.
  • Terapkan penyimpanan persisten untuk lampiran jenis konten.
  • Berikan rute untuk membuat lampiran serta menayangkan Tampilan Pengajar dan iframe Tampilan Siswa.
  • Berikan permintaan berikut ke API add-on Google Classroom:
    • Buat lampiran baru.
    • Dapatkan konteks add-on, yang mengidentifikasi apakah pengguna yang login adalah siswa atau pengajar.

Setelah selesai, Anda dapat membuat lampiran jenis konten pada tugas melalui UI Google Classroom saat login sebagai pengajar. Guru dan siswa di kelas juga dapat melihat kontennya.

Mengaktifkan Classroom API

Lakukan panggilan ke Classroom API dimulai dengan langkah ini. API harus diaktifkan untuk project Google Cloud sebelum Anda dapat melakukan panggilan ke project tersebut. Navigasi ke entri library Google Classroom API, lalu pilih Aktifkan.

Menangani parameter kueri Tampilan Penemuan Lampiran

Seperti yang telah dibahas sebelumnya, Google Classroom meneruskan parameter kueri saat memuat Tampilan Penemuan Lampiran di iframe:

  • courseId: ID kursus Classroom saat ini.
  • itemId: ID unik untuk CourseWork, CourseWorkMaterial, atau Pengumuman yang menerima lampiran add-on.
  • itemType: "courseWork", "courseWorkMaterials" atau "pengumuman".
  • addOnToken: Token yang digunakan untuk memberi otorisasi Tindakan add-on Classroom.
  • login_hint: ID Google pengguna saat ini.

Panduan ini membahas courseId, itemId, itemType, dan addOnToken. Simpan dan teruskan saat melakukan panggilan ke Classroom API.

Seperti pada langkah panduan sebelumnya, simpan nilai parameter kueri yang diteruskan di sesi kita. Kita harus melakukannya saat Tampilan Penemuan Lampiran pertama kali dibuka, karena inilah satu-satunya kesempatan bagi Classroom untuk meneruskan parameter kueri ini.

Python

Buka file server Flask Anda yang menyediakan rute untuk Lampiran Tampilan Penemuan (attachment-discovery-routes.py jika Anda mengikuti yang diberikan). Di bagian atas rute landing add-on (/classroom-addon dalam contoh yang kami berikan), ambil dan simpan Parameter kueri courseId, itemId, itemType, dan addOnToken.

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

Menuliskan nilai-nilai ini ke sesi hanya jika nilai-nilai tersebut ada; mereka tidak diteruskan lagi jika pengguna kebetulan kembali ke Tampilan Penemuan Lampiran tanpa menutup iframe.

Menambahkan penyimpanan persisten untuk lampiran jenis konten

Anda memerlukan data lokal untuk setiap lampiran yang dibuat. Hal ini memungkinkan Anda mencari konten yang dipilih pengajar menggunakan ID yang disediakan oleh Classroom.

Menyiapkan skema database untuk Attachment. Contoh yang kami berikan menampilkan lampiran yang menampilkan gambar dan keterangan. Attachment berisi atribut berikut:

  • attachment_id: ID unik untuk lampiran. Ditugaskan oleh Classroom dan dimunculkan dalam respons saat membuat lampiran.
  • image_filename: Nama file lokal dari gambar yang akan ditampilkan.
  • image_caption: Teks yang akan ditampilkan bersama gambar.

Python

Memperluas implementasi SQLite dan flask_sqlalchemy dari langkah sebelumnya.

Buka file tempat Anda telah menentukan tabel Pengguna (models.py) jika Anda mengikuti contoh yang kami berikan). Tambahkan kode berikut di bagian bawah file di bawah class 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))

Impor kelas Lampiran baru ke file server dengan lampiran Anda rute yang sangat spesifik.

Menyiapkan rute baru

Mulai langkah panduan ini dengan menyiapkan beberapa halaman baru di aplikasi kami. Dengan add-on ini, pengguna dapat membuat dan melihat konten melalui add-on kami.

Menambahkan rute pembuatan lampiran

Anda memerlukan halaman bagi pengajar untuk memilih konten dan mengeluarkan pembuatan lampiran permintaan. Menerapkan rute /attachment-options untuk menampilkan opsi konten untuk dipilih oleh pengajar. Anda juga memerlukan {i>template<i} untuk pemilihan konten dan halaman konfirmasi pembuatan. Contoh yang kami sediakan berisi {i>template<i} untuk ini, dan juga dapat menampilkan permintaan serta respons dari API Classroom.

Perlu diketahui bahwa Anda dapat mengubah Tampilan Penemuan Lampiran yang ada halaman landing untuk menampilkan opsi konten, bukan membuat halaman baru /attachment-options. Sebaiknya buat halaman baru untuk tujuan latihan ini agar Anda dapat mempertahankan perilaku SSO dalam detik langkah panduan, seperti pencabutan izin aplikasi. Cara ini seharusnya membuktikan berguna saat Anda membangun dan menguji add-on.

Seorang guru dapat memilih dari sekumpulan kecil gambar dengan teks di contoh. Kami telah menyediakan empat gambar tempat terkenal yang teksnya berasal dari nama {i>file<i}.

Python

Dalam contoh yang kami berikan, nilainya ada dalam file 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,
    )

Tindakan ini menghasilkan "Buat Lampiran" yang terlihat seperti berikut:

Tampilan pemilihan konten contoh Python

Pengajar dapat memilih beberapa gambar. Buat satu lampiran untuk setiap gambar yang dipilih pengajar dalam metode create_attachments.

Permintaan pembuatan lampiran masalah

Setelah mengetahui konten mana yang ingin dilampirkan oleh pengajar, mengajukan permintaan ke Classroom API untuk membuat lampiran di penugasan Anda. Simpan detail lampiran dalam database Anda setelah menerima respons dari Classroom API.

Mulai dengan mendapatkan instance layanan Classroom:

Python

Dalam contoh yang kami berikan, nilainya ada dalam file 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)

Kirimkan permintaan CREATE ke courses.courseWork.addOnAttachments endpoint. Untuk setiap gambar yang dipilih oleh pengajar, pertama-tama buat Objek AddOnAttachment:

Python

Dalam contoh yang kami berikan, ini adalah kelanjutan dari 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}",
    }

Setidaknya kolom teacherViewUri, studentViewUri, dan title harus yang disediakan untuk setiap lampiran. teacherViewUri dan studentViewUri menunjukkan URL yang dimuat ketika lampiran dibuka oleh jenis pengguna terkait.

Kirim objek AddOnAttachment dalam isi permintaan ke entitas yang sesuai Endpoint addOnAttachments. Berikan courseId, itemId, itemType, dan ID addOnToken dengan setiap permintaan.

Python

Dalam contoh yang kami berikan, ini adalah kelanjutan dari 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()

Buat entri untuk lampiran ini dalam {i>database<i} lokal sehingga Anda nanti dapat memuat konten yang benar. Classroom menampilkan nilai id yang unik dalam merespons permintaan pembuatan, jadi gunakan ini sebagai kunci utama dalam di skrip untuk menyiapkan database. Perhatikan juga bahwa Classroom meneruskan attachmentId parameter kueri saat membuka Tampilan Guru dan Siswa:

Python

Dalam contoh yang kami berikan, ini adalah kelanjutan dari 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()

Pertimbangkan mengarahkan pengguna ke halaman konfirmasi pada tahap ini, mengakui bahwa mereka telah berhasil membuat lampiran.

Mengizinkan lampiran dari add-on Anda

Sekarang adalah waktu yang tepat untuk menambahkan alamat yang sesuai ke Lampiran yang Diizinkan Kolom Awalan URI di Konfigurasi Aplikasi Google Workspace Marketplace SDK kami. Add-on Anda hanya dapat membuat lampiran dari salah satu awalan URI yang tercantum pada halaman ini. Ini adalah langkah pengamanan untuk membantu mengurangi kemungkinan terjadinya serangan {i>man-in-the-middle<i}.

Pendekatan paling sederhana adalah menyediakan {i>domain level<i} teratas Anda di bidang ini, untuk contoh https://example.com. https://localhost:<your port number>/ akan bekerja jika Anda menggunakan komputer lokal Anda sebagai server web.

Menambahkan rute untuk Tampilan Pengajar dan Siswa

Ada empat iframe tempat add-on Google Classroom dimuat. Oleh karena itu, Anda hanya membuat rute yang menayangkan iframe Tampilan Penemuan Lampiran jauh. Berikutnya, tambahkan rute untuk menayangkan juga iframe Tampilan Pengajar dan Siswa.

iframe Tampilan Pengajar diperlukan untuk menampilkan pratinjau siswa pengalaman, tetapi dapat secara opsional mencakup informasi tambahan atau pengeditan baru.

Tampilan Siswa adalah halaman yang ditampilkan kepada setiap siswa ketika mereka membuka lampiran add-on.

Untuk tujuan latihan ini, buat satu /load-content-attachment rute yang menyajikan Tampilan Pengajar dan Siswa. Menggunakan Classroom API untuk menentukan apakah pengguna adalah pengajar atau siswa ketika halaman memuat.

Python

Dalam contoh yang kami berikan, nilainya ada dalam file 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")

Ingatlah bahwa Anda juga harus mengautentikasi pengguna pada tahap ini. Anda juga harus menangani parameter kueri login_hint di sini, dan mengarahkan pengguna ke alur otorisasi Anda jika diperlukan. Lihat detail panduan login yang dibahas dalam panduan sebelumnya untuk informasi selengkapnya tentang alur ini.

Lalu kirim permintaan ke endpoint getAddOnContext yang cocok dengan item .

Python

Dalam contoh yang kami berikan, ini adalah kelanjutan dari Metode 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()

Metode ini menampilkan informasi tentang peran pengguna saat ini di class. Mengubah tampilan yang ditampilkan kepada pengguna, bergantung pada perannya. Tepatnya salah satu Kolom studentContext atau teacherContext diisi dalam respons Google Cloud Platform. Periksa ini untuk menentukan cara menyapa pengguna.

Dalam kasus apa pun, gunakan nilai parameter kueri attachmentId untuk mengetahui lampiran yang akan diambil dari {i>database<i} kita. Parameter kueri ini disediakan saat membuka URI Tampilan Pengajar atau Siswa.

Python

Dalam contoh yang kami berikan, ini adalah kelanjutan dari Metode 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)

Menguji add-on

Selesaikan langkah-langkah berikut untuk menguji pembuatan lampiran:

  • Login ke [Google Classroom] sebagai salah satu Pengajar menguji pengguna.
  • Pilih tab Tugas Kelas dan buat Tugas baru.
  • Klik tombol Add-on di bawah area teks, lalu pilih add-on Anda. iframe akan terbuka dan add-on memuat URI Penyiapan Lampiran yang Anda yang ditentukan di halaman Konfigurasi Aplikasi Google Workspace Marketplace SDK.
  • Pilih konten untuk dilampirkan ke tugas.
  • Tutup iframe setelah alur pembuatan lampiran selesai.

Anda akan melihat kartu lampiran muncul di UI pembuatan tugas di Google Google Classroom. Klik kartu untuk membuka iframe Tampilan Pengajar dan mengonfirmasi tempat lampiran yang benar muncul. Klik tombol Tetapkan.

Selesaikan langkah-langkah berikut untuk menguji pengalaman siswa:

  • Lalu login ke Classroom sebagai pengguna uji coba siswa di akun yang sama sebagai pengguna uji coba pengajar.
  • Temukan tugas tes di tab Tugas Kelas.
  • Luaskan tugas dan klik kartu lampiran untuk membuka Tampilan Siswa iframe.

Pastikan lampiran yang benar muncul untuk siswa.

Selamat! Anda siap untuk melanjutkan ke langkah berikutnya: membuat lampiran jenis aktivitas.