پیوست های نوع محتوا

این چهارمین بررسی در مجموعه مروری بر افزونه‌های Classroom است.

در این راهنما، شما با Google Classroom API برای ایجاد پیوست‌ها تعامل دارید. شما مسیرهایی را در اختیار کاربران قرار می دهید تا محتوای پیوست را مشاهده کنند. نماها بسته به نقش کاربر در کلاس متفاوت است. این راهنما پیوست‌های نوع محتوا را پوشش می‌دهد که نیازی به ارسال دانش‌آموز ندارند.

در طول این راهنما موارد زیر را تکمیل می کنید:

  • پارامترهای پرس و جوی افزودنی زیر را بازیابی و استفاده کنید:
    • addOnToken : یک رمز مجوز که به نمای کشف پیوست ارسال می شود.
    • itemId : یک شناسه منحصر به فرد برای CourseWork، CourseWorkMaterial یا اعلامیه که پیوست الحاقی را دریافت می کند.
    • itemType : یا "courseWork"، "courseWorkMaterials" یا "Announcement".
    • courseId : یک شناسه منحصر به فرد برای دوره Google Classroom که در آن تکلیف در حال ایجاد است.
    • attachmentId : شناسه منحصر به فردی است که توسط Google Classroom به یک پیوست افزودنی پس از ایجاد اختصاص داده می شود.
  • ذخیره سازی دائمی را برای پیوست های نوع محتوا پیاده سازی کنید.
  • مسیرهایی را برای ایجاد پیوست‌ها و ارائه iframe‌های Teacher View و Student View ارائه کنید.
  • درخواست‌های زیر را برای API افزونه‌های Google Classroom صادر کنید:
    • یک پیوست جدید ایجاد کنید.
    • زمینه افزودنی را دریافت کنید، که مشخص می کند کاربر وارد شده دانش آموز یا معلم است.

پس از اتمام، می‌توانید هنگام ورود به عنوان معلم، پیوست‌هایی از نوع محتوا در تکالیف از طریق رابط کاربری Google Classroom ایجاد کنید. معلمان و دانش آموزان کلاس نیز می توانند مطالب را مشاهده کنند.

Classroom API را فعال کنید

با این مرحله با Classroom API تماس بگیرید. قبل از اینکه بتوانید با آن تماس بگیرید، API باید برای پروژه Google Cloud شما فعال باشد. به ورودی کتابخانه Google Classroom API بروید و فعال کردن را انتخاب کنید.

پارامترهای جستجوی مشاهده کشف پیوست را مدیریت کنید

همانطور که قبلاً بحث شد ، Google Classroom پارامترهای جستجو را هنگام بارگیری نمای کشف پیوست در iframe ارسال می کند:

  • courseId : شناسه دوره فعلی Classroom.
  • itemId : یک شناسه منحصر به فرد برای CourseWork، CourseWorkMaterial یا اعلامیه که پیوست الحاقی را دریافت می کند.
  • itemType : یا "courseWork"، "courseWorkMaterials" یا "Announcement".
  • addOnToken : رمزی که برای مجوز دادن به برخی از اقدامات الحاقی Classroom استفاده می شود.
  • login_hint : شناسه Google کاربر فعلی.
  • hd : دامنه میزبان برای کاربر فعلی، مانند example.com .

این راهنما به courseId , itemId , itemType و addOnToken می پردازد . هنگام برقراری تماس با API Classroom، این موارد را حفظ کرده و ارسال کنید.

مانند مرحله پیشین قبلی، مقادیر پارامتر پرس و جو ارسال شده را در جلسه خود ذخیره کنید. زمانی که نمای کشف پیوست برای اولین بار باز می شود، مهم است که این کار را انجام دهیم، زیرا این تنها فرصتی است که Classroom این پارامترهای پرس و جو را ارسال می کند.

پایتون

به فایل سرور Flask خود بروید که مسیرهایی را برای نمای کشف پیوست ارائه می دهد (اگر از مثال ارائه شده ما پیروی می کنید attachment-discovery-routes.py ). در بالای مسیر فرود افزونه خود ( /classroom-addon در مثال ارائه شده ما)، پارامترهای پرس و جو courseId ، itemId ، itemType و 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")

این مقادیر را فقط در صورت وجود در جلسه بنویسید. اگر کاربر بعداً بدون بستن iframe به نمای کشف پیوست بازگردد، دوباره ارسال نمی‌شوند.

ذخیره سازی دائمی برای پیوست های نوع محتوا اضافه کنید

شما به یک رکورد محلی از هر پیوست ایجاد شده نیاز دارید. این به شما امکان می دهد محتوایی را که معلم با استفاده از شناسه های ارائه شده توسط Classroom انتخاب کرده است، جستجو کنید.

یک طرح پایگاه داده برای Attachment تنظیم کنید. مثال ارائه شده ما پیوست هایی را ارائه می دهد که یک تصویر و یک شرح را نشان می دهد. یک Attachment شامل ویژگی های زیر است:

  • attachment_id : یک شناسه منحصر به فرد برای پیوست. توسط Classroom تخصیص داده شد و در هنگام ایجاد پیوست در پاسخ بازگردانده شد.
  • image_filename : نام فایل محلی تصویر برای نمایش.
  • image_caption : شرحی که باید با تصویر نشان داده شود.

پایتون

اجرای SQLite و flask_sqlalchemy را از مراحل قبل گسترش دهید.

به فایلی بروید که جدول کاربر خود را در آن تعریف کرده اید (اگر از مثال ارائه شده ما پیروی می کنید models.py ). موارد زیر را در پایین فایل زیر کلاس 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))

کلاس پیوست جدید را با مسیرهای مدیریت پیوست خود به فایل سرور وارد کنید.

راه اندازی مسیرهای جدید

این مرحله را با راه اندازی چند صفحه جدید در برنامه ما آغاز کنید. اینها به کاربر اجازه می دهد محتوا را از طریق افزونه ما ایجاد و مشاهده کند.

مسیرهای ایجاد پیوست را اضافه کنید

شما به صفحاتی نیاز دارید تا معلم بتواند محتوا را انتخاب کند و درخواست ایجاد پیوست را صادر کند. مسیر /attachment-options برای نمایش گزینه‌های محتوا برای انتخاب معلم اجرا کنید. شما همچنین به الگوهایی برای صفحات تأیید انتخاب و ایجاد محتوا نیاز دارید. نمونه‌های ارائه‌شده ما حاوی الگوهایی برای این موارد است و همچنین می‌تواند درخواست‌ها و پاسخ‌های API Classroom را نمایش دهد.

توجه داشته باشید که می‌توانید به‌جای ایجاد صفحه /attachment-options جدید، صفحه فرود نمای کشف پیوست خود را برای نمایش گزینه‌های محتوا تغییر دهید. توصیه می‌کنیم صفحه جدیدی برای اهداف این تمرین ایجاد کنید تا رفتار SSO اجرا شده در مرحله دوم را حفظ کنید، مانند لغو مجوزهای برنامه. اینها باید هنگام ساختن و آزمایش افزونه خود مفید واقع شوند.

یک معلم می تواند از مجموعه کوچکی از تصاویر زیرنویس در مثال ارائه شده ما انتخاب کند. ما چهار تصویر از مکان‌های دیدنی معروف ارائه کرده‌ایم که شرح آنها از نام فایل‌ها گرفته شده است.

پایتون

در مثال ارائه شده ما، این در فایل 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,
    )

این یک صفحه "ایجاد پیوست" را ایجاد می کند که شبیه موارد زیر است:

نمای انتخاب محتوای نمونه پایتون

معلم می تواند چندین تصویر را انتخاب کند. برای هر تصویری که معلم در روش create_attachments انتخاب کرده است، یک پیوست ایجاد کنید.

درخواست ایجاد پیوست را صادر کنید

اکنون که می‌دانید معلم می‌خواهد کدام قسمت از محتوا را ضمیمه کند، درخواست‌هایی را به Classroom API ارسال کنید تا پیوست‌هایی برای تکلیف ما ایجاد کند. پس از دریافت پاسخ از API Classroom، جزئیات پیوست را در پایگاه داده خود ذخیره کنید.

با دریافت نمونه ای از سرویس Classroom شروع کنید:

پایتون

در مثال ارائه شده ما، این در فایل 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.
    # We need to request the Classroom API from a specific URL while add-ons
    # are in Early Access.

    # A Google API Key can be created in your Google Cloud project's Credentials
    # settings: https://console.cloud.google.com/apis/credentials.
    # Click "Create Credentials" at top and choose "API key", then provide
    # the key in the discoveryServiceUrl below.
    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)

یک درخواست CREATE را به courses.courseWork.addOnAttachments پایان دهید. برای هر تصویر انتخاب شده توسط معلم، ابتدا یک شی AddOnAttachment بسازید:

پایتون

در مثال ارائه شده ما، این ادامه روش 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}",
    }

حداقل فیلدهای teacherViewUri ، studentViewUri و title باید برای هر پیوست ارائه شود. teacherViewUri و studentViewUri نشان دهنده URL هایی هستند که هنگام باز شدن پیوست توسط نوع کاربر مربوطه بارگذاری می شوند.

شی AddOnAttachment را در بدنه درخواست به نقطه پایانی addOnAttachments ارسال کنید. با هر درخواست شناسه های courseId ، itemId ، itemType و addOnToken را ارائه دهید.

پایتون

در مثال ارائه شده ما، این ادامه روش 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()

یک ورودی برای این پیوست در پایگاه داده محلی خود ایجاد کنید تا بتوانید بعداً محتوای صحیح را بارگیری کنید. Classroom یک مقدار id منحصر به فرد را در پاسخ به درخواست ایجاد برمی گرداند، بنابراین از آن به عنوان کلید اصلی در پایگاه داده ما استفاده کنید. همچنین توجه داشته باشید که Classroom هنگام باز کردن نماهای معلم و دانش‌آموز، پارامتر query attachmentId را ارسال می‌کند:

پایتون

در مثال ارائه شده ما، این ادامه روش 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()

مسیریابی کاربر را در این مرحله به یک صفحه تأیید در نظر بگیرید و تصدیق کنید که پیوست‌ها را با موفقیت ایجاد کرده‌اند.

به پیوست‌های افزونه خود اجازه دهید

اکنون زمان مناسبی است تا هر آدرس مناسبی را به قسمت Allowed Attachment URI Prefixes در صفحه پیکربندی برنامه GWM SDK اضافه کنید. افزونه شما فقط می تواند از یکی از پیشوندهای URI فهرست شده در این صفحه پیوست ایجاد کند. این یک اقدام امنیتی برای کمک به کاهش احتمال حملات انسان در میان است.

ساده ترین روش ارائه دامنه سطح بالای خود در این زمینه است، به عنوان مثال https://example.com . https://localhost:<your port number>/ اگر از دستگاه محلی خود به عنوان وب سرور استفاده می کنید کار می کند.

مسیرهایی را برای نمای معلم و دانش آموز اضافه کنید

چهار iframe وجود دارد که ممکن است افزونه Google Classroom در آنها بارگیری شود. شما تاکنون فقط مسیرهایی ساخته‌اید که به iframe نمای کشف پیوست خدمت می‌کنند. در مرحله بعد، مسیرهایی را اضافه کنید تا iframe های Teacher و Student View را نیز ارائه دهند.

iframe Teacher View برای نمایش پیش‌نمایش تجربه دانش‌آموز مورد نیاز است، اما می‌تواند به صورت اختیاری شامل اطلاعات اضافی یا ویژگی‌های ویرایش باشد.

نمای دانشجو صفحه ای است که به هر دانش آموز هنگام باز کردن یک پیوست افزودنی ارائه می شود.

برای اهداف این تمرین، یک مسیر واحد /load-content-attachment ایجاد کنید که هم به نمای معلم و هم به نمای دانش آموز خدمت کند. از متدهای Classroom API برای تعیین اینکه آیا کاربر معلم است یا دانش آموز هنگام بارگیری صفحه استفاده کنید.

پایتون

در مثال ارائه شده ما، این در فایل 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")

به خاطر داشته باشید که در این مرحله باید کاربر را نیز احراز هویت کنید. همچنین باید پارامترهای login_hint و hd query را در اینجا مدیریت کنید و در صورت لزوم کاربر را به جریان مجوز خود هدایت کنید. برای کسب اطلاعات بیشتر در مورد این جریان، به جزئیات راهنمای ورود به سیستم که در مراحل پیشین بحث شده است، مراجعه کنید.

سپس درخواستی را به نقطه پایانی getAddOnContext ارسال کنید که با نوع مورد مطابقت دارد.

پایتون

در مثال ارائه شده ما، این ادامه روش load_content_attachment است.

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

این متد اطلاعات مربوط به نقش کاربر فعلی در کلاس را برمی گرداند. نمای ارائه شده به کاربر را بسته به نقش او تغییر دهید. دقیقاً یکی از فیلدهای studentContext یا teacherContext در شی پاسخ پر شده است. اینها را بررسی کنید تا مشخص کنید چگونه کاربر را خطاب قرار دهید.

در هر صورت، از مقدار پارامتر query attachmentId استفاده کنید تا بدانید کدام پیوست را از پایگاه داده ما بازیابی کنید. این پارامتر پرس و جو هنگام باز کردن URI های Teacher یا Student View ارائه می شود.

پایتون

در مثال ارائه شده ما، این ادامه روش 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)

افزونه را تست کنید

مراحل زیر را برای آزمایش ایجاد پیوست انجام دهید:

  • به عنوان یکی از کاربران آزمون معلم خود به [Google Classroom] وارد شوید.
  • به برگه Classwork بروید و یک تکلیف جدید ایجاد کنید.
  • روی دکمه Add-ons در زیر ناحیه متن کلیک کنید، سپس افزونه خود را انتخاب کنید. iframe باز می شود و افزونه URI تنظیمات پیوست را که در صفحه پیکربندی برنامه GWM SDK مشخص کرده اید بارگیری می کند.
  • یک قطعه از محتوا را برای پیوست به تکلیف انتخاب کنید.
  • پس از اتمام جریان ایجاد پیوست، iframe را ببندید.

باید ببینید که یک کارت پیوست در رابط کاربری ایجاد تکلیف در Google Google Classroom ظاهر می‌شود. روی کارت کلیک کنید تا کادر نمای معلم باز شود و تأیید کنید که پیوست درست ظاهر می شود. روی دکمه Assign کلیک کنید.

مراحل زیر را برای آزمایش تجربه دانشجویی کامل کنید:

  • سپس به عنوان کاربر آزمون دانش آموز در همان کلاس با کاربر آزمون معلم وارد Classroom شوید.
  • تکلیف آزمون را در برگه Classwork پیدا کنید.
  • تکلیف را بزرگ کنید و روی کارت پیوست کلیک کنید تا iframe نمای دانشجو باز شود.

تأیید کنید که پیوست صحیح برای دانش آموز ظاهر می شود.

تبریک می گویم! برای ادامه مرحله بعدی آماده هستید: ایجاد پیوست‌های نوع فعالیت .