İçerik türü ekler

Bu, Classroom eklentileriyle ilgili dördüncü adım adım açıklama videosudur.

Bu adım adım açıklamalı kılavuzda, ekler 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 rotalar sağlarsınız. Görünümler, kullanıcının sınıftaki rolüne bağlı olarak değişir. Bu kılavuzda, öğrenci gönderimi gerektirmeyen içerik türü ekleri ele alınmaktadır.

Bu kılavuzda aşağıdaki işlemleri yapacaksınız:

  • Aşağıdaki eklenti sorgu parametrelerini alın ve kullanın:
    • addOnToken: Attachment Discovery View'a iletilen bir yetkilendirme jetonu.
    • itemId: Eklenti ekini alan CourseWork, CourseWorkMaterial veya Announcement'ın benzersiz tanımlayıcısı.
    • itemType: "courseWork", "courseWorkMaterials" veya "announcement" değerlerinden biri.
    • courseId: Ödevin oluşturulduğu Google Classroom kursunun benzersiz tanımlayıcısı.
    • attachmentId: Google Classroom tarafından oluşturulduktan sonra bir eklenti ekine atanan benzersiz tanımlayıcı.
  • İçerik türü ekleri için kalıcı depolama alanı uygulayın.
  • Ek oluşturma ve Öğretmen Görünümü ile Öğrenci Görünümü iFrame'lerini sunma rotaları sağlar.
  • Google Classroom eklentileri API'sine aşağıdaki istekleri gönderin:
    • Yeni bir ek oluşturun.
    • Eklenti bağlamını alın. Bu bağlam, oturum açmış kullanıcının öğrenci mi yoksa öğretmen mi olduğunu tanımlar.

İşlem tamamlandıktan sonra, öğretmen olarak giriş yaptığınızda Google Classroom kullanıcı arayüzü üzerinden ödevlere içerik türü ekleri oluşturabilirsiniz. Sınıftaki öğretmenler ve öğrenciler de içeriği görüntüleyebilir.

Classroom API'yi etkinleştirme

Bu adımdan başlayarak Classroom API'ye çağrı yapın. API'ye çağrı yapabilmeniz için Google Cloud projenizde etkinleştirilmesi gerekir. Google Classroom API kitaplık girişine gidin ve Etkinleştir'i seçin.

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

Daha önce belirtildiği gibi, Google Classroom, iFrame'de Ek Bulma Görünümü yüklenirken sorgu parametrelerini iletir:

  • courseId: Mevcut Classroom kursunun kimliği.
  • itemId: Eklenti ekini alan CourseWork, CourseWorkMaterial veya Announcement'ın benzersiz tanımlayıcısı.
  • itemType: "courseWork", "courseWorkMaterials" veya "announcement" değerlerinden biri.
  • addOnToken: Belirli Classroom eklenti 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çıklama courseId, itemId, itemType ve addOnToken ile ilgilidir. 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 iletmesi için tek fırsat bu olduğundan, Ek Bulma Görünümü ilk açıldığında bunu yapmamız önemlidir.

Python

Ek Bulma Görünümü için rotalar sağlayan Flask sunucunuzun dosyasına gidin (attachment-discovery-routes.py, sağladığımız örneği takip ediyorsanız). Eklenti açılış rotanızın en üstünde (sağladığımız örnekte /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 mevcutsa oturuma yazın. Kullanıcı, iframe'i kapatmadan daha sonra Ek Bulma Görünümü'ne dönerse bu değerler tekrar iletilmez.

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

Oluşturulan 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.

Attachment için bir veritabanı şeması oluşturun. Sağladığımız örnekte, bir resim ve bir başlık gösteren ekler yer almaktadır. Attachment öğesi aşağıdaki özellikleri içerir:

  • attachment_id: Ekin benzersiz tanımlayıcısı. 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 takip ediyorsanız). Aşağıdaki kodu dosyanın en altına, User sınıfının altına 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 kılavuz adımına, uygulamamızda bazı 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 istekleri göndermesi için sayfalar gerekir. Öğretmenin seçebileceği içerik seçeneklerini göstermek için /attachment-options rotasını uygulayın. Ayrıca içerik seçimi ve oluşturma onayı sayfaları için de şablonlara ihtiyacınız vardır. Sağladığımız örneklerde bunların şablonları bulunur ve Classroom API'den gelen istekler ile yanıtlar da gösterilebilir.

Alternatif olarak, yeni bir /attachment-options sayfası oluşturmak yerine mevcut ek bulma görünümü açılış sayfanızı değiştirerek içerik seçeneklerini gösterebileceğinizi unutmayın. İkinci adımda uygulanan SSO davranışını (ör. uygulama izinlerinin iptali) korumak için bu alıştırma kapsamında yeni bir sayfa oluşturmanızı öneririz. Bunlar, eklentinizi oluşturup test ederken faydalı olacaktır.

Öğretmenler, sağladığımız örnekteki küçük bir altyazılı resim grubundan seçim yapabilir. Altyazıları dosya adlarından türetilen ünlü simge yapıların dört resmini paylaştık.

Python

Sağladığımız örnekte bu, 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ğıdaki gibi bir "Ek Oluştur" sayfası oluşturur:

Python örneği içerik seçimi 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 öğrendiğinize göre, ö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

Sağladığımız örnekte bu, 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

Sağlanan örneğimizde bu, 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ından 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.

AddOnAttachment nesnesini, isteğin gövdesinde uygun addOnAttachments uç noktasına gönderin. Her istekte courseId, itemId, itemType ve addOnToken tanımlayıcılarını gönderin.

Python

Sağlanan örneğimizde bu, 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 nedenle, veritabanımızda birincil anahtar olarak bu değeri kullanın. Classroom'un, Öğretmen ve Öğrenci Görünümleri'ni açarken attachmentId sorgu parametresini ilettiğini de unutmayın:

Python

Sağlanan örneğimizde bu, 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ı, ekleri başarıyla oluşturduğunu onaylayan bir onay sayfasına yönlendirebilirsiniz.

Eklentinizden eklerin gönderilmesine izin verme

Şimdi, 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 iyi bir zaman. Eklentiniz yalnızca bu sayfada listelenen URI öneklerinden birini kullanarak ek oluşturabilir. Bu, ortadaki adam saldırısı olasılığını azaltmaya yardımcı olan bir güvenlik önlemidir.

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

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

Google Classroom eklentisinin yüklenebileceği dört iFrame vardır. Şu ana kadar yalnızca Ek Bulma Görünümü iFrame'ine hizmet veren rotalar oluşturdunuz. Ardından, Öğretmen ve Öğrenci Görünümü iFrame'lerini de sunmak için rotalar ekleyin.

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

Öğrenci Görünümü, bir eklenti ekini açtıklarında her öğrenciye gösterilen sayfadır.

Bu alıştırma kapsamında, hem Öğretmen hem de Öğrenci Görünümü'ne hizmet eden tek bir /load-content-attachment rota oluşturun. Sayfa yüklendiğinde kullanıcının öğretmen mi yoksa öğrenci mi olduğunu belirlemek için Classroom API yöntemlerini kullanın.

Python

Sağladığımız örnekte bu, 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 de doğrulamanız gerektiğini unutmayın. Ayrıca, login_hint sorgu parametresini burada işlemeli ve gerekirse kullanıcıyı yetkilendirme akışınıza yönlendirmelisiniz. Bu akış hakkında daha fazla bilgi için önceki adım adım açıklamalarda ele alınan girişle ilgili rehberlik ayrıntılarına bakın.

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

Python

Sağlanan örneğimizde bu, load_content_attachment yönteminin devamıdır.

# 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üyle ilgili bilgileri döndürür. Kullanıcının rolüne bağlı olarak gösterilen görünümü değiştirme response object içinde 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ğınızı öğrenmek için attachmentId sorgu parametresi değerini kullanın. Bu sorgu parametresi, Öğretmen veya Öğrenci Görünümü URI'leri açılırken sağlanır.

Python

Sağlanan örneğimizde bu, load_content_attachment yönteminin devamıdır.

# 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şturmayı test etmek için aşağıdaki adımları tamamlayın:

  • [Google Classroom]'da öğretmen test kullanıcılarınızdan biri olarak oturum açın.
  • Sınıf çalışmaları sekmesine gidip yeni bir ödev oluşturun.
  • Metin alanının altındaki Eklentiler düğmesini tıklayın ve eklentinizi seçin. Iframe açılır ve eklenti, Google Workspace Marketplace SDK'sının Uygulama Yapılandırması sayfasında belirttiğiniz Ek Kurulumu URI'sini yükler.
  • Ödeve eklemek istediğiniz içeriği 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ünür. Öğretmen Görünümü iFrame'ini açmak için kartı tıklayın ve doğru eklerin göründüğünü onaylayın. Ata düğmesini tıklayın.

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

  • Ardından, öğretmen test kullanıcısıyla aynı sınıfta öğrenci test kullanıcısı olarak Classroom'da oturum açın.
  • Test ödevini Sınıf çalışmaları sekmesinde 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 eklerin göründüğünü onaylayın.

Tebrikler! Bir sonraki adıma geçmeye hazırsınız: Etkinlik türü ekleri oluşturma.