İçerik türü ekler

Bu, Classroom eklentileri açıklamalı kılavuz serisinin dördüncü bölümüdür.

Bu adım adım açıklamalı kılavuzda, ek oluşturmak için Google Classroom API ile etkileşim kurarsınız. Kullanıcıların ek içeriğini görüntüleyebileceği yollar sağlarsınız. Görünümler, kullanıcının sınıftaki rolüne bağlı olarak farklılık gösterir. Bu adım adım açıklamalı kılavuzda, öğrenci gönderimi gerektirmeyen içerik türü ekleri ele alınmaktadır.

Bu adım adım açıklamalı kılavuzda şunları tamamlarsınız:

  • Aşağıdaki eklenti sorgu parametrelerini alıp kullanın:
    • addOnToken: Ek Keşfi Görünümü'ne iletilen bir yetkilendirme jetonu.
    • itemId: Eklenti ekini alan Ödev, Ödev Materyali veya Duyuru için benzersiz tanımlayıcı.
    • itemType: "courseWork", "courseWorkMaterials" veya "announcement".
    • courseId: Ödevin oluşturulduğu Google Classroom kursu için benzersiz bir tanımlayıcı.
    • attachmentId: Google Classroom tarafından eklenti eki oluşturulduktan sonra eklentiye atanan benzersiz tanımlayıcı.
  • İçerik türü ekleri için kalıcı depolama alanı uygulayın.
  • Ekler oluşturmak ve öğretmen görünümü ile öğrenci görünümü iFrame'lerini yayınlamak için rotalar sağlayın.
  • Google Classroom eklentileri API'sine aşağıdaki istekleri gönderin:
    • Yeni bir ek oluşturun.
    • Giriş yapan kullanıcının öğrenci mi yoksa öğretmen mi olduğunu tanımlayan eklenti bağlamını alın.

Bu işlemi tamamladıktan sonra, öğretmen olarak giriş yaptığınızda Google Classroom kullanıcı arayüzünü kullanarak ödevlere içerik türündeki ekler oluşturabilirsiniz. Sınıftaki öğretmenler ve öğrenciler de içeriği görüntüleyebilir.

Classroom API'yi etkinleştirme

Bu adımdan itibaren Classroom API'ye çağrı yapın. API'ye çağrı gönderebilmeniz için Google Cloud projeniz için etkinleştirilmiş olması gerekir. Google Classroom API kitaplık girişine gidin ve Etkinleştir'i seçin.

Ek Keşif Görünümü sorgu parametrelerini işleme

Daha önce de belirtildiği gibi, Google Classroom, iframe'e Ek Keşfi Görünümü'nü yüklerken sorgu parametrelerini iletir:

  • courseId: Geçerli Classroom kursunun kimliği.
  • itemId: Eklenti ekini alan Ödev, Ödev Materyali veya Duyuru için benzersiz tanımlayıcı.
  • itemType: "courseWork", "courseWorkMaterials" veya "announcement".
  • addOnToken: Belirli Classroom eklentisi işlemlerini yetkilendirmek için kullanılan bir jeton.
  • login_hint: Geçerli kullanıcının Google kimliği.

Bu adım adım açıklamalı kılavuzda courseId, itemId, itemType ve addOnToken ele alınmaktadır. Classroom API'ye çağrı gönderirken bunları saklayın ve iletin.

Önceki adımda olduğu gibi, iletilen sorgu parametresi değerlerini oturumumuzda saklayın. Classroom'un bu sorgu parametrelerini iletebileceği tek fırsat, ek keşif görünümü ilk açıldığında olduğu için bunu bu görünüm ilk açıldığında yapmamız önemlidir.

Python

Ek Keşfi Görünümü için rotalar sağlayan Flask sunucu dosyanıza gidin (sağladığımız örneği izliyorsanız attachment-discovery-routes.py). Eklenti açılış rotanızın en üstünde (örnekteki /classroom-addon), courseId, itemId, itemType ve addOnToken sorgu parametrelerini alıp saklayın.

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

Bu değerleri yalnızca mevcut olduklarında oturuma yazın. Kullanıcı, iframe'i kapatmadan daha sonra Ek Keşfi Görünümü'ne dönerse bu değerler tekrar iletilmez.

İçerik türündeki ekler için kalıcı depolama alanı ekleme

Oluşturulan tüm eklerin yerel bir kaydına ihtiyacınız vardır. Bu sayede, Classroom tarafından sağlanan tanımlayıcıları kullanarak öğretmenin seçtiği içeriği arayabilirsiniz.

Bir Attachment için veritabanı şeması oluşturun. Sağladığımız örnekte, bir resim ve altyazı gösteren ekler gösterilmektedir. Attachment aşağıdaki özellikleri içerir:

  • attachment_id: Ekin için benzersiz tanımlayıcı. Classroom tarafından atanır ve ek oluşturulurken yanıtta döndürülür.
  • image_filename: Gösterilecek resmin yerel dosya adı.
  • image_caption: Resimle birlikte gösterilecek altyazı.

Python

Önceki adımlardaki SQLite ve flask_sqlalchemy uygulamasını genişletin.

Kullanıcı tablonuzu tanımladığınız dosyaya gidin (models.py sağladığımız örneği izliyorsanız). Dosyanın alt kısmına, User sınıfının altına aşağıdakileri ekleyin.

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

Yeni Attachment sınıfını, ek işleme rotalarınızla birlikte sunucu dosyasına aktarın.

Yeni rotalar oluşturma

Bu adım adım açıklamalı kılavuzun ilk adımını uygulamamızda yeni sayfalar oluşturarak başlayın. Bu izinler, kullanıcıların eklentimiz aracılığıyla içerik oluşturmasına ve görüntülemesine olanak tanır.

Ek oluşturma rotaları ekleme

Öğretmenin içerik seçmesi ve ek oluşturma isteği göndermesi için sayfalara ihtiyacınız vardır. Öğretmenin seçebileceği içerik seçeneklerini görüntülemek için /attachment-options rotasını uygulayın. İçerik seçimi ve oluşturma onayı sayfaları için de şablonlara ihtiyacınız vardır. Sağlanan örneklerde bu şablonlar yer alır ve Classroom API'den gelen istekler ve yanıtlar da gösterilebilir.

Alternatif olarak, yeni /attachment-options sayfası oluşturmak yerine mevcut Ek Keşfi Görünümü açılış sayfanızı içerik seçeneklerini gösterecek şekilde değiştirebileceğinizi unutmayın. İkinci adımda uygulanan SSO davranışını (ör. uygulama izinlerinin iptal edilmesi) korumak için bu alıştırma amacıyla yeni bir sayfa oluşturmanızı öneririz. Bu bilgiler, eklentinizi oluşturup test ederken faydalı olacaktır.

Öğretmenler, sunduğumuz örnekteki altyazı eklenmiş resimlerden seçim yapabilir. Altyazılarını dosya adlarından alan, ünlü simgelerin yer aldığı dört resim sağladık.

Python

Bu, verdiğimiz örnekte webapp/attachment_routes.py dosyasındadır.

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

Bu işlem, aşağıdakine benzer bir "Ek Oluştur" sayfası oluşturur:

Python örnek içerik seçim görünümü

Öğretmen birden fazla resim seçebilir. Öğretmenin create_attachments yönteminde seçtiği her resim için bir ek oluşturun.

Sorun eki oluşturma istekleri

Öğretmenin hangi içerikleri eklemek istediğini öğrendiniz. Şimdi, ödevimize ek oluşturmak için Classroom API'ye istek gönderin. Classroom API'den yanıt aldıktan sonra ek ayrıntılarını veritabanınızda saklayın.

Classroom hizmetinin bir örneğini alarak başlayın:

Python

Bu, verdiğimiz örnekte webapp/attachment_routes.py dosyasındadır.

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)

courses.courseWork.addOnAttachments uç noktasına bir CREATE isteği gönderin. Öğretmen tarafından seçilen her resim için önce bir AddOnAttachment nesnesi oluşturun:

Python

Bu, verdiğimiz örnekte create_attachments yönteminin devamıdır.

# 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}",
    }

Her ek için en az teacherViewUri, studentViewUri ve title alanları sağlanmalıdır. teacherViewUri ve studentViewUri, ek ilgili kullanıcı türü tarafından açıldığında yüklenen URL'leri temsil eder.

İsteğin gövdesinde uygun addOnAttachments uç noktasına AddOnAttachment nesnesini gönderin. Her istekle birlikte courseId, itemId, itemType ve addOnToken tanımlayıcılarını sağlayın.

Python

Bu, verdiğimiz örnekte create_attachments yönteminin devamıdır.

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

Daha sonra doğru içeriği yükleyebilmek için yerel veritabanınızda bu ek için bir giriş oluşturun. Classroom, oluşturma isteğine yanıt olarak benzersiz bir id değeri döndürür. Bu değeri veritabanımızda birincil anahtar olarak kullanın. Classroom'un, Öğretmen ve Öğrenci Görünümleri'ni açarken attachmentId sorgu parametresini ilettiğini de unutmayın:

Python

Bu, verdiğimiz örnekte create_attachments yönteminin devamıdır.

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

Bu noktada kullanıcıyı, ek oluşturduklarını onaylayan bir onay sayfasına yönlendirebilirsiniz.

Eklentinizle ek göndermeye izin verme

Google Workspace Marketplace SDK'sının Uygulama Yapılandırması sayfasındaki İzin Verilen Ek URI Önekleri alanına uygun adresleri eklemek için bu fırsattan yararlanabilirsiniz. Eklentiniz yalnızca bu sayfada listelenen URI ön eklerinden birinden ek oluşturabilir. Bu, ortadaki adam saldırılarının olasılığını azaltmaya yardımcı olan bir güvenlik önlemidir.

En basit yaklaşım, bu alana üst düzey alan adınızı (ör. https://example.com) girmektir. https://localhost:<your port number>/, web sunucusu olarak yerel makinenizi kullanıyorsanız işe yarar.

Öğretmen ve öğrenci görünümleri için rota ekleme

Google Classroom eklentisinin yüklenmesi için dört iFrame vardır. Şimdiye kadar yalnızca Attachment Discovery View iFrame'sini yayınlayan rotalar oluşturdunuz. Ardından, öğretmen ve öğrenci görünümü iFrame'lerini de yayınlamak için rotalar ekleyin.

Öğrenci deneyiminin önizlemesini göstermek için Öğretmen Görünümü iFrame'i gereklidir ancak isteğe bağlı olarak ek bilgiler veya düzenleme özellikleri içerebilir.

Öğrenci Görünümü, eklenti eklerini açan her öğrenciye gösterilen sayfadır.

Bu alıştırma için hem öğretmen hem de öğrenci görünümünü sunan tek bir /load-content-attachment rota oluşturun. Sayfa yüklendiğinde kullanıcının öğretmen mi öğrenci mi olduğunu belirlemek için Classroom API yöntemlerini kullanın.

Python

Bu, verdiğimiz örnekte webapp/attachment_routes.py dosyasındadır.

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

Bu noktada kullanıcının kimliğini doğrulamanız gerektiğini unutmayın. Burada login_hint sorgu parametresini de işlemeniz ve gerekirse kullanıcıyı yetkilendirme akışınıza yönlendirmeniz gerekir. Bu akış hakkında daha fazla bilgi için önceki adım adım açıklamalı kılavuzlarda ele alınan giriş kılavuzu ayrıntılarına bakın.

Ardından, öğe türüyle eşleşen getAddOnContext uç noktasına bir istek gönderin.

Python

Bu, verdiğimiz örnekte load_content_attachment yönteminin devamı niteliğindedir.

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

Bu yöntem, mevcut kullanıcının sınıftaki rolü hakkında bilgi döndürür. Kullanıcıya sunulan görünümü, rolüne göre değiştirin. Yanıt nesnesi'nde studentContext veya teacherContext alanlarından tam olarak biri doldurulur. Kullanıcıya nasıl hitap edeceğinizi belirlemek için bunları inceleyin.

Her durumda, veritabanımızdan hangi eki alacağımızı öğrenmek için attachmentId sorgu parametresi değerini kullanın. Bu sorgu parametresi, öğretmen veya öğrenci görünümü URI'leri açıldığında sağlanır.

Python

Bu, verdiğimiz örnekte load_content_attachment yönteminin devamı niteliğindedir.

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

Eklentiyi test etme

Ek oluşturma işlemini test etmek için aşağıdaki adımları uygulayın:

  • [Google Classroom]'da öğretmen test kullanıcılarınızdan biri olarak oturum açın.
  • Sınıf çalışmaları sekmesine gidin ve yeni bir Ödev oluşturun.
  • Metin alanının altındaki Eklentiler düğmesini tıklayın ve ardından eklentinizi seçin. İçeriden yerleştirilmiş çerçeve açılır ve eklenti, Google Workspace Marketplace SDK'sının Uygulama Yapılandırması sayfasında belirttiğiniz Ekleme Kurulumu URI'sini yükler.
  • Ödeve eklenecek bir içerik seçin.
  • Ek oluşturma akışı tamamlandıktan sonra iFrame'i kapatın.

Google Classroom'daki ödev oluşturma kullanıcı arayüzünde bir ek kartı görürsünüz. Öğretmen Görünümü iframe'ini açmak için kartı tıklayın ve doğru eki gördüğünüzden emin olun. Ata düğmesini tıklayın.

Öğrenci deneyimini test etmek için aşağıdaki adımları uygulayın:

  • Ardından, Classroom'da öğretmen test kullanıcısıyla aynı sınıftaki bir öğrenci test kullanıcısı olarak oturum açın.
  • Sınıf çalışmaları sekmesinde test ödevini bulun.
  • Ödevi genişletin ve öğrenci görünümü iFrame'ini açmak için ek kartını tıklayın.

Öğrenci için doğru eki gördüğünüzden emin olun.

Tebrikler! Bir sonraki adıma (etkinlik türündeki ekleri oluşturma) geçmeye hazırsınız.