İçerik türü ekler

Bu, Classroom eklentileri adım adım açıklamalı dördüncü kılavuzudur.

Bu adım adım açıklamalı kılavuzda, ek oluşturmak için Google Classroom API ile etkileşime geçeceksiniz. Kullanıcıların ek içeriğini görüntülemeleri için rotalar sağlarsınız. Görünümler, kullanıcının sınıftaki rolüne göre farklılık gösterir. Bu adım adım açıklamalı kılavuzda, öğrencinin göndermesi gerekmeyen içerik türü ekleri ele alınmaktadır.

Bu adım adım açıklamalı kılavuz kapsamında aşağıdaki işlemleri tamamlayacaksı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 CourseWork, CourseWorkMaterial veya duyuru için benzersiz bir tanımlayıcı.
    • itemType: "courseWork", "courseWorkMaterials" veya "duyuru".
    • courseId: Ödevin oluşturulduğu Google Classroom dersinin benzersiz tanımlayıcısı.
    • attachmentId: Google Classroom tarafından, oluşturulduktan sonra eklenti ekine atanan benzersiz tanımlayıcı.
  • İçerik türündeki ekler için kalıcı depolama alanı uygulayın.
  • Ek oluşturmak ve Öğretmen Görünümü ile Öğrenci Görünümü iframe'lerini sunmak 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.

İşiniz bittiğinde, öğretmen olarak giriş yaptığınızda Google Classroom kullanıcı arayüzü üzerinden ödevlerde içerik türünde ekler oluşturabilirsiniz. Sınıftaki öğretmen 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. Google Cloud projenize çağrı yapabilmeniz için API'nin projenizde etkinleştirilmiş olması 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 de belirtildiği gibi, Google Classroom iframe'de Ek Keşif Görünümü'nü yüklerken sorgu parametrelerini iletir:

  • courseId: Geçerli Classroom dersinin kimliği.
  • itemId: Eklenti ekini alan CourseWork, CourseWorkMaterial veya duyuru için benzersiz bir tanımlayıcı.
  • itemType: "courseWork", "courseWorkMaterials" veya "duyuru".
  • 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ı yayınlarken bunları saklayın ve iletin.

Önceki adım adım açıklamalı kılavuz adımında olduğu gibi, iletilen sorgu parametresi değerlerini oturumumuzda depolayın. Classroom'un bu sorgu parametrelerini iletebilmesi için tek fırsat bu olduğundan, bunu Ek Keşif Görünümü ilk açıldığında gerçekleştirmemiz önemlidir.

Python

Ek Keşfi Görünümü için rotalar sağlayan Flask sunucusu dosyanıza gidin (sağlanan örneğimizi takip ediyorsanız attachment-discovery-routes.py). Eklentinizin açılış rotasının en üst kısmında (sağlanan örneğimizde /classroom-addon) courseId, itemId, itemType ve addOnToken sorgu parametrelerini alın ve depolayı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 oturuma yalnızca bu değerler mevcutsa yazın; kullanıcı daha sonra iframe'i kapatmadan Ek Keşif Görünümü'ne dönerse tekrar iletilmez.

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

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

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

  • attachment_id: Eklerin benzersiz tanımlayıcısıdır. Classroom tarafından atanır ve ek oluşturulurken yanıtta geri döndürülür.
  • image_filename: Görüntülenecek resmin yerel dosya adı.
  • image_caption: Resimle birlikte gösterilecek başlıktır.

Python

Önceki adımlarda açıklanan SQLite ve flask_sqlalchemy uygulamasını genişletin.

Kullanıcı tablonuzu tanımladığınız dosyaya gidin (sağladığımız örneği takip ediyorsanız models.py). Aşağıdakini 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 Ek sınıfını, ek işleme rotalarınızla birlikte sunucu dosyasına aktarın.

Yeni rotalar oluşturun

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

Ek oluşturma rotası ekleme

Öğretmenin içerik seçmesi ve ek oluşturma isteklerinde bulunması 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ğladığımız örneklerde bunlara yönelik şablonlar bulunur ve Classroom API'den gelen istek ve yanıtlar da gösterilebilir.

Alternatif olarak, yeni /attachment-options sayfasını oluşturmak yerine mevcut Ek Keşif Görünümü açılış sayfanızı içerik seçeneklerini görüntüleyecek şekilde değiştirebilirsiniz. İkinci adım adım açıklamalı adımda uygulanan, uygulama izinlerinin iptali gibi TOA davranışını korumak için bu alıştırmada yeni bir sayfa oluşturmanızı öneririz. Bunlar, eklentinizi derleyip test ederken işinize yarayacaktır.

Öğretmen, sağladığımız örnekte küçük bir altyazılı resim grubundan seçim yapabilir. Başlıkları dosya adlarından türetilen ünlü önemli noktaların dört resmini sağladık.

Python

Sağlanan örneğimizde 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ğıdakine benzeyen bir "Ek Oluştur" sayfası oluşturur:

Python örnek 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.

Ek oluşturma isteklerinde sorun

Artık öğretmenin hangi içerik parçalarını eklemek istediğini bildiğinize göre, ödevmizde ek oluşturma konusunda Classroom API'ye istek gönderebilirsiniz. Classroom API'den yanıt aldıktan sonra ek ayrıntılarını veritabanınızda depolayın.

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

Python

Sağlanan örneğimizde 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ğladığımız örneğimizde bu, create_attachments yönteminin bir 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 gösterir.

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

Python

Sağladığımız örneğimizde bu, create_attachments yönteminin bir 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 üzere bu ek için yerel veritabanınızda bir giriş oluşturun. Classroom, oluşturma isteğinin yanıtında benzersiz bir id değeri döndürür. Bu nedenle, bunu veritabanımızda birincil anahtar olarak kullanın. Ayrıca Classroom'un, Öğretmen ve Öğrenci Görünümlerini açarken attachmentId sorgu parametresini ilettiğini de unutmayın:

Python

Sağladığımız örneğimizde bu, create_attachments yönteminin bir 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ı bir onay sayfasına yönlendirmeyi düşünün ve ekleri başarıyla oluşturduklarını onaylayın.

Eklentinizden eklere izin verin

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

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

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

Google Classroom eklentilerinin yüklenebileceği dört iframe vardır. Şimdiye kadar yalnızca Ek Keşif 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 rota ekleyin.

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

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

Bu alıştırmada hem Öğretmen hem de Öğrenci Görünümüne hizmet veren tek bir /load-content-attachment yönlendirmesi 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ğlanan örneğimizde 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 burada login_hint sorgu parametresini işlemeli ve gerekirse kullanıcıyı yetkilendirme akışınıza yönlendirmelisiniz. Bu akış hakkında daha fazla bilgi edinmek için önceki adım adım açıklamalı kılavuzlarda açıklanan giriş kılavuzu ayrıntılarına göz atın.

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

Python

Sağladığımız örneğimizde bu, load_content_attachment yönteminin bir devamıdır.

# Create an instance of the Classroom service.
classroom_service = googleapiclient.discovery.build(
    serviceName="classroom"
    version="v1",
    discoveryServiceUrl=f"https://classroom.googleapis.com/$discovery/rest?labels=ADD_ONS_ALPHA&key={GOOGLE_API_KEY}",
    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, geçerli kullanıcının sınıftaki rolüyle ilgili bilgileri döndürür. Kullanıcıya sunulan görünümü, rolüne bağlı olarak değiştirin. Yanıt nesnesinde tam olarak studentContext veya teacherContext alanlarından 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çıldığında sağlanır.

Python

Sağladığımız örneğimizde bu, load_content_attachment yönteminin bir 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ı 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. 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ünecektir. Öğretmen Görünümü iframe'ini açmak için kartı tıklayın ve doğru ekin 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ı ile aynı sınıfta yer alan bir öğrenci test kullanıcısı olarak Classroom'da oturum açın.
  • Sınıf Çalışmaları sekmesinde test ödevini bulun.
  • Ödevi genişletin ve ek kartını tıklayarak Öğrenci Görünümü iframe'ini açın.

Öğrenci için doğru ekin görüntülendiğini onaylayın.

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