Ek notları ve geri verilen notları geri verme

Bu, Classroom eklentilerindeki adım adım açıklamalı altıncı kılavuzdur. size yol gösterir.

Bu adım adım açıklamalı kılavuzda, önceki adım adım açıklamalı kılavuzda verilen örneği değiştireceksiniz. notlu etkinlik türü eki oluşturmak için. Ayrıca, bir notu da geri alırsınız Google Classroom'a programatik olarak gönderilir (öğretmen notunda gösterilir) geçici not olarak alabilirsiniz.

Bu adım adım açıklamalı kılavuz, serideki diğer örneklerden biraz farklı olsa da notları öğrenciye geri vermek için iki olası yaklaşım sunar Classroom. Her ikisinin de geliştirici ve kullanıcı üzerinde ayrı etkileri vardır. deneyimler; Classroom eklentinizi tasarlarken her ikisini de göz önünde bulundurun. Aşağıdaki konular hakkında daha fazla bilgi için Eklerle etkileşim kurma rehberi sayfamızı okuyun. bazı en iyi uygulamalardan bahsedeceğiz.

API'deki notlandırma özelliklerinin isteğe bağlı olduğunu unutmayın. Bunlarla birlikte etkinlik türü eklerini kullanabilirsiniz.

Bu adım adım açıklamalı kılavuz kapsamında aşağıdaki işlemleri tamamlayacaksınız:

  • Önceki ek oluşturma isteklerini Classroom API'yi kullanarak ekin paydasını da ayarlayabilirsiniz.
  • Öğrencinin gönderimini programatik olarak puanlayın ve ekin not payı.
  • Ödevin notunu geçmek için iki yaklaşım uygulamak Oturum açmış veya çevrimdışı öğretmen kimlik bilgilerini kullanan Classroom.

Tamamladığınızda, notlar geri verilen gösterim davranışı tetiklenir. Bunun tam olarak ne zaman gerçekleşeceği, benimsetme sürecidir.

Bu örneğin amacı doğrultusunda, önceki öğrenciye ünlü bir önemli noktanın resminin gösterildiği ve kullanıcının adını girmeniz istenir. Öğrenci bir eke tam not atadıysa doğru adı girer, aksi takdirde sıfır değerini alır.

Classroom eklentileri API'sinin not verme özelliğini anlama

Eklentiniz ekleyebilirsiniz. Bunlar sırasıyla pointsEarned ve maxPoints kullanılarak ayarlanır. değerlerini API'de bulabilirsiniz. Classroom kullanıcı arayüzünde bir ek kartı gösteriliyor. ayarlandığında maxPoints değerini alır.

Bir tarafta maxPoints içeren birden fazla ek örneği
atama

Şekil 1. Ödev oluşturma kullanıcı arayüzünde, maxPoints ayarlanmış.

Classroom eklentileri API'si, ek notları için kazanılan puan. Bunlar ödev notları için de ekleyebilirsiniz. Ancak, ödev not ayarları şu şekildedir: Not senkronizasyonu etiketinin bulunduğu ekin ek notu ayarları ekleyeceksiniz. "Not senkronizasyonu" ek, pointsEarned öğesini şunun için ayarlıyor: öğrencinin ödevle ilgili geçici notunu da belirler.

Genellikle, dosyanın 3-3 saat içinde olabileceği maxPoints, "Not senkronizasyonu"nu alır etiket. Ödev oluşturma kullanıcı arayüzünü inceleyin "Not senkronizasyonu" örneği için Şekil 1'de gösterilen örnek etiket. Lütfen "Ek 1" kartta "Not senkronizasyonu" yazıyor ve ödeve verdiğiniz notun kırmızı kutu 50 puan olarak güncellendi. Her ne kadar Şekil 1'de üç ek kartı gösteriyorsa yalnızca bir kartta "Not senkronizasyonu" yazıyor etiket. Bu mevcut uygulamanın önemli bir kısıtlaması: yalnızca bir ek "Not senkronizasyonu" etiket ekleyin.

maxPoints öğesini ayarlayan birden fazla ek varsa "Not senkronizasyonu" ekini içeren "Not senkronizasyonu"nu etkinleştirmez herhangi bir ek kaldı. maxPoints özelliğini ayarlayan başka bir ek eklendiğinde, Yeni ekte not senkronizasyonu sağladığınızda, maksimum ödev notu şuna ayarlanır: eşleşmesini sağlar. Hangi ekin "Not senkronizasyonu" veya belirli bir ödevin kaç ekin olduğunu görebilirsiniz.

Bir ekin maksimum notunu belirleme

Bu bölümde, ek notu için paydaşın nasıl ayarlanacağı açıklanmaktadır; verileri tüm öğrencilerin sınavlarında alabileceği maksimum puandır. gönderimler. Bunun için ekin maxPoints değerini ayarlayın.

Bu özelliğin etkinleştirilmesi için mevcut uygulamamızda yalnızca küçük bir değişiklik yapılması gerekir: notlandırma özelliklerini kullanıyor. Ek oluştururken maxPoints değerini studentWorkReviewUri öğesini içeren aynı AddOnAttachment nesnesi, teacherViewUri ve diğer ek alanları.

Yeni bir ödev için varsayılan maksimum puanın 100 olduğunu unutmayın. Önerilerimiz doğrulayabilmeniz için maxPoints ayarını 100'den farklı bir değere notlar doğru şekilde ayarlanıyor. Örnek olarak maxPoints değerini 50 olarak ayarlayın:

Python

attachment nesnesini oluştururken maxPoints alanını ekleyin, yalnızca bir CREATE isteği göndermeden önce courses.courseWork.addOnAttachments uç nokta. Bu bilgiye webapp/attachment_routes.py dosyası oluşturun.

attachment = {
    # Specifies the route for a teacher user.
    "teacherViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True),
    },
    # Specifies the route for a student user.
    "studentViewUri": {
        "uri":
            flask.url_for(
                "load_activity_attachment",
                _scheme='https',
                _external=True)
    },
    # Specifies the route for a teacher user when the attachment is
    # loaded in the Classroom grading view.
    "studentWorkReviewUri": {
        "uri":
            flask.url_for(
                "view_submission", _scheme='https', _external=True)
    },
    # Sets the maximum points that a student can earn for this activity.
    # This is the denominator in a fractional representation of a grade.
    "maxPoints": 50,
    # The title of the attachment.
    "title": f"Attachment {attachment_count}",
}

Bu gösterimde, maxPoints değerini yerel Ek veritabanınız; ek bir API çağrısı yapma zorunluluğundan kurtarır. öğrenci gönderimlerine not verirken. Bununla birlikte, bazı durumlarda öğretmenler, ödev not ayarlarını eklentinizden bağımsız olarak değiştirebilir. Gönder görmek için courses.courseWork uç noktasına GET isteği atama düzeyinde maxPoints değeri. Bunu yaparken itemId öğesini CourseWork.id alanı.

Şimdi veritabanı modelinizi, ekin maxPoints değerini de içerecek şekilde güncelleyin. CREATE yanıtındaki maxPoints değerini kullanmanızı öneririz:

Python

İlk olarak Attachment tablosuna bir max_points alanı ekleyin. Bunu bulabilirsiniz: webapp/models.py dosyasına ekleyin.

# Database model to represent an attachment.
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))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

courses.courseWork.addOnAttachments CREATE isteğine geri dönün. Mağaza yanıtta döndürülen maxPoints değeri.

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,
    # Store the maxPoints value returned in the response.
    max_points=int(resp.get("maxPoints")))
db.session.add(new_attachment)
db.session.commit()

Ekin maksimum not artık var. Bu davranışı test edebilmeniz gerekir şimdi; yeni ödeve iliştirin ve ek kartının "Not senkronizasyonu"nu gösterir etiketini ve ödevin "Puan"ı değer değişiklikleridir.

Classroom'da öğrenci gönderim notu belirleme

Bu bölümde, ek notu için payın nasıl belirleneceği açıklanmaktadır; yani, Ek için tek bir öğrencinin puanı. Bunun için bir öğrenci ayarlayın gönderimin pointsEarned değeri.

Artık vermeniz gereken önemli bir karar var: Eklentiniz kullanıcılara nasıl pointsEarned ayarlamak istiyor musunuz?

Sorun, pointsEarned ayarının teacher OAuth kapsamını gerektirmesinden kaynaklanmaktadır. Öğrenci kullanıcılara teacher kapsamı vermemelisiniz; sonuç olarak öğrencilerin eklentinizle etkileşime geçmesi veya Öğrenci Görünümü iframe'i yerine Öğretmen Görünümü iframe'i. Bu nedenle iki pointsEarned ayarlama seçenekleri:

  • Giriş yapmış öğretmenin kimlik bilgilerini kullanma.
  • Depolanmış (çevrimdışı) öğretmen kimlik bilgilerini kullanma.

Aşağıdaki bölümlerde daha önce her bir yaklaşımın denge adım adım anlatacağız. Sağladığımız örneklerde, her ikisi de Classroom'a not geçme yaklaşımını benimser; bkz. aşağıdaki dile özel talimatları inceleyebilirsiniz: verilen örnekleri çalıştırın:

Python

En üstte SET_GRADE_WITH_LOGGED_IN_USER_CREDENTIALS beyanını bulun /webapp/attachment_routes.py dosya. Geri vermek için bu değeri True olarak ayarlayın notları verebilirsiniz. Bu değeri False olarak ayarla öğrenci şu ödevi gönderdiğinde, saklanan kimlik bilgilerini kullanarak notları geri vermek etkinliği'ne dokunun.

Oturum açmış öğretmenin kimlik bilgilerini kullanarak notları ayarlama

pointsEarned ayarını yapma isteğinde bulunmak için oturum açmış kullanıcının kimlik bilgilerini kullanın. Uygulamanın geri kalanını yansıttığından bu yöntem oldukça sezgisel görünecektir ve gerçekleştirmek için fazla çaba sarf etmiyor.

Ancak, öğretmenin yalnızca öğrencinin ödeviyle etkileşimde bulunduğunu Öğrenci Çalışma İncelemesi iframe'inde gönderim. Bu yaklaşımda çıkarım:

  • Öğretmen geçene kadar Classroom'da notlar doldurulmaz işlemi nasıl yapılır?
  • Tüm öğeleri doldurmak için bir öğretmenin her öğrenci gönderisini öğrenci notları.
  • Classroom'un notu alması arasında kısa bir gecikme yaşanıyor ve Classroom kullanıcı arayüzündeki görünümü. Gecikme genellikle 5-10 saniye sürer ancak 30 saniyeye kadar da uzayabilir.

Bu faktörlerin birlikte kullanılması, öğretmenlerin sınıf notlarını tamamen doldurmak için önemli, zaman alıcı manuel çalışmalardır.

Bu yaklaşımı uygulamak için mevcut Öğrencinize bir API çağrısı daha ekleyin İş İncelemesi rotası.

Öğrenci gönderimini ve ek kayıtlarını aldıktan sonra öğrencinin gönderimini yapabilir ve alınan notu saklayabilir. Notu AddOnAttachmentStudentSubmission nesnesinin pointsEarned alanı. En son, şuna bir PATCH isteği gönder: courses.courseWork.addOnAttachments.studentSubmissions uç nokta İstek gövdesinde AddOnAttachmentStudentSubmission örneği. Lütfen PATCH isteğimizdeki updateMask öğesinde pointsEarned değerini de belirtmemiz gerekiyor:

Python

# Look up the student's submission in our database.
student_submission = Submission.query.get(flask.session["submissionId"])

# Look up the attachment in the database.
attachment = Attachment.query.get(student_submission.attachment_id)

grade = 0

# See if the student response matches the stored name.
if student_submission.student_response.lower(
) == attachment.image_caption.lower():
    grade = attachment.max_points

# Create an instance of the Classroom service.
classroom_service = ch._credential_handler.get_classroom_service()

# Build an AddOnAttachmentStudentSubmission instance.
add_on_attachment_student_submission = {
    # Specifies the student's score for this attachment.
    "pointsEarned": grade,
}

# Issue a PATCH request to set the grade numerator for this attachment.
patch_grade_response = classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

Çevrimdışı öğretmen kimlik bilgilerini kullanarak notları belirleme

Notları belirlemeye yönelik ikinci yaklaşımda depolanan kimlik bilgilerinin kullanılması gerekir. . Bu uygulama, önceden yetkilendirilmiş bir öğretmenin yenilemesini kullanarak kimlik bilgilerini jetonlara erişebilir ve ardından bu kimlik bilgilerini kullanarak pointsEarned ayarını yapabilirsiniz.

Bu yaklaşımın kritik bir avantajı, notların sorunları önlemek için Classroom kullanıcı arayüzünde öğretmen işlemi yukarıda belirtilmiştir. Sonuç olarak son kullanıcılar, notlandırma deneyimini algılar. sorunsuz ve verimli. Ayrıca bu yaklaşım, ekibinizin notları geri verdiğiniz an; örneğin öğrencilerin ödevini tamamlamaları etkinliği veya eşzamansız olarak olması gerekir.

Bu yaklaşımı uygulamak için aşağıdaki görevleri tamamlayın:

  1. Erişim jetonu depolamak için kullanıcı veritabanı kayıtlarını değiştirme
  2. Ek veritabanı kayıtlarını öğretmen kimliğini depolayacak şekilde değiştirme.
  3. Öğretmenin kimlik bilgilerini alın ve (isteğe bağlı olarak) yeni bir Classroom hizmeti örneği.
  4. Gönderimin notunu belirleyebilirsiniz.

Bu sunumun amaçları doğrultusunda, öğrenci tamamladığında notu belirleyin Etkinlik; yani öğrenci, formu Öğrenci Görünümüne gönderdiğinde yol gösterir.

Erişim jetonunu depolamak için kullanıcı veritabanı kayıtlarını değiştirme

API çağrıları yapmak için iki benzersiz jeton gereklidir: yenileme jetonu ve erişim jetonundan yararlanabilirsiniz. Şimdiye kadar bu adım adım açıklamalı kılavuz serisini takip ettiyseniz User tablo şemasında bir yenileme jetonu zaten depolanmalıdır. Yenilemeyi depolama jeton yalnızca oturum açmış kullanıcıyla API çağrıları yaptığınızda yeterlidir, kimlik doğrulama akışının parçası olarak bir erişim jetonu alırsınız.

Ancak, artık oturum açmış kullanıcı dışında biri olarak arama yapmanız gerekir. kimlik doğrulama akışının kullanılamadığı anlamına gelir. Bu nedenle, erişim jetonunun eklenmesine olanak tanır. User tablo şemanızı şu şekilde güncelleyin: bir erişim jetonu ekleyin:

Python

Sağlanan örneğimizde bu, webapp/models.py dosyasındadır.

# Database model to represent a user.
class User(db.Model):
    # The user's identifying information:
    id = db.Column(db.String(120), primary_key=True)
    display_name = db.Column(db.String(80))
    email = db.Column(db.String(120), unique=True)
    portrait_url = db.Column(db.Text())

    # The user's refresh token, which will be used to obtain an access token.
    # Note that refresh tokens will become invalid if:
    # - The refresh token has not been used for six months.
    # - The user revokes your app's access permissions.
    # - The user changes passwords.
    # - The user belongs to a Google Cloud organization
    #   that has session control policies in effect.
    refresh_token = db.Column(db.Text())

    # An access token for this user.
    access_token = db.Column(db.Text())

Ardından, User kaydı oluşturan veya güncelleyen kodları güncelleyerek erişim jetonu:

Python

Sağlanan örneğimizde bu, webapp/credential_handler.py dosyasındadır.

def save_credentials_to_storage(self, credentials):
    # Issue a request for the user's profile details.
    user_info_service = googleapiclient.discovery.build(
        serviceName="oauth2", version="v2", credentials=credentials)
    user_info = user_info_service.userinfo().get().execute()
    flask.session["username"] = user_info.get("name")
    flask.session["login_hint"] = user_info.get("id")

    # See if we have any stored credentials for this user. If they have used
    # the add-on before, we should have received login_hint in the query
    # parameters.
    existing_user = self.get_credentials_from_storage(user_info.get("id"))

    # If we do have stored credentials, update the database.
    if existing_user:
        if user_info:
            existing_user.id = user_info.get("id")
            existing_user.display_name = user_info.get("name")
            existing_user.email = user_info.get("email")
            existing_user.portrait_url = user_info.get("picture")

        if credentials and credentials.refresh_token is not None:
            existing_user.refresh_token = credentials.refresh_token
            # Update the access token.
            existing_user.access_token = credentials.token

    # If not, this must be a new user, so add a new entry to the database.
    else:
        new_user = User(
            id=user_info.get("id"),
            display_name=user_info.get("name"),
            email=user_info.get("email"),
            portrait_url=user_info.get("picture"),
            refresh_token=credentials.refresh_token,
            # Store the access token as well.
            access_token=credentials.token)

        db.session.add(new_user)

    db.session.commit()

Öğretmen kimliğini depolamak için Ek veritabanı kayıtlarını değiştirme

Bir etkinliğe not vermek için pointsEarned numaralı telefonu arayarak ayrıntılı bir şekilde anlatacağım. Bunu yapmanın birkaç yolu vardır:

  • Öğretmen kimlik bilgilerinin ders kimliklerine yerel olarak eşlenmesini sağlayın. Bununla birlikte, aynı öğretmen her zaman belli bir dersle ilişkili olmayabilir.
  • Classroom API courses uç noktasına yönelik GET isteklerini şu kullanıcıya gönderin: mevcut öğretmenleri görün. Ardından, iki hedefin yerini belirlemek için yerel kullanıcı kayıtlarını eşleşen öğretmen kimlik bilgileri.
  • Eklenti eki oluştururken öğretmen kimliğini yerel ekleyebilirsiniz. Ardından, attachmentId, Öğrenci Görünümü iframe'ine geçirildi.

Bu örnekte, Öğrenci bir etkinlik ekini tamamladığında.

Veritabanınızın Attachment tablosuna öğretmen kimliği alanı ekleyin:

Python

Sağlanan örneğimizde bu, webapp/models.py dosyasındadır.

# Database model to represent an attachment.
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))

    # The maximum number of points for this activity.
    max_points = db.Column(db.Integer)

    # The ID of the teacher that created the attachment.
    teacher_id = db.Column(db.String(120))

Ardından, Attachment kaydı oluşturan veya güncelleyen kodları şu şekilde güncelleyin: içerik üreticinin kimliğini depolama:

Python

Sağladığımız örneğimizde bu, create_attachments webapp/attachment_routes.py dosya

# Store the attachment 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,
    max_points=int(resp.get("maxPoints")),
    teacher_id=flask.session["login_hint"])
db.session.add(new_attachment)
db.session.commit()

Öğretmenin kimlik bilgilerini alma

Öğrenci Görünümü iframe'ini sunan rotayı bulun. Depolandıktan hemen sonra öğrencinin yanıtını yerel veritabanınıza kaydederseniz, öğretmenin yerel depolama alanınızdaki kimlik bilgilerinden yararlanın. Bu, hesaba katılan adımları uygulayın. Bunları, yeni bir kitle oluşturmak için de öğretmen kullanıcı için Classroom hizmeti örneği:

Python

Sağladığımız örneğimizde bu, load_activity_attachment yöntemindeki webapp/attachment_routes.py dosyası.

# Create an instance of the Classroom service using the tokens for the
# teacher that created the attachment.

# We're assuming that there are already credentials in the session, which
# should be true given that we are adding this within the Student View
# route; we must have had valid credentials for the student to reach this
# point. The student credentials will be valid to construct a Classroom
# service for another user except for the tokens.
if not flask.session.get("credentials"):
    raise ValueError(
        "No credentials found in session for the requested user.")

# Make a copy of the student credentials so we don't modify the original.
teacher_credentials_dict = deepcopy(flask.session.get("credentials"))

# Retrieve the requested user's stored record.
teacher_record = User.query.get(attachment.teacher_id)

# Apply the user's tokens to the copied credentials.
teacher_credentials_dict["refresh_token"] = teacher_record.refresh_token
teacher_credentials_dict["token"] = teacher_record.access_token

# Construct a temporary credentials object.
teacher_credentials = google.oauth2.credentials.Credentials(
    **teacher_credentials_dict)

# Refresh the credentials if necessary; we don't know when this teacher last
# made a call.
if teacher_credentials.expired:
    teacher_credentials.refresh(Request())

# Request the Classroom service for the specified user.
teacher_classroom_service = googleapiclient.discovery.build(
    serviceName=CLASSROOM_API_SERVICE_NAME,
    version=CLASSROOM_API_VERSION,
    credentials=teacher_credentials)

Gönderimin notunu belirleme

Buradaki prosedür, oturum açmış öğretmenin kimlik bilgileri ekleyin. Ancak, aramayı öğretmenle yapmanız gerektiğini unutmayın Önceki adımda alınan kimlik bilgileri:

Python

# Issue a PATCH request as the teacher to set the grade numerator for this
# attachment.
patch_grade_response = teacher_classroom_service.courses().courseWork(
).addOnAttachments().studentSubmissions().patch(
    courseId=flask.session["courseId"],
    itemId=flask.session["itemId"],
    attachmentId=flask.session["attachmentId"],
    submissionId=flask.session["submissionId"],
    # updateMask is a list of fields being modified.
    updateMask="pointsEarned",
    body=add_on_attachment_student_submission).execute()

Eklentiyi test etme

Önceki adım adım açıklamalı kılavuza benzer şekilde, etkinlik türü içeren bir atama oluşturun ekleyebilir, öğrenci olarak yanıt gönderebilir ve ardından öğretmen olarak Öğrenci Çalışma İncelemesi iframe'inde gönderim. Görmeniz gereken not, uygulama yaklaşımınıza bağlı olarak farklı zamanlarda görünebilir:

  • Öğrenci etkinliği tamamladığında bir notu geri vermeyi seçtiyseniz cevap notlarını açmadan önce arayüzde geçici notlarını göreceksiniz. Öğrenci Çalışması İncelemesi iframe'i. Bunu öğrenci listesinde de görebilirsiniz. ödevi açıp "Not" sekmesinde Öğrenci Çalışması'nın yanındaki kutucuk iframe'i inceleyin.
  • Öğretmen Öğrenci Çalışması'nı açtığında notu geri vermeyi seçtiyseniz iframe'i inceleyin; not, "Not" bölümünde görünür kutusundan kısa bir süre sonra iframe yüklenir. Yukarıda belirtildiği gibi bu işlem 30 saniyeyi bulabilir. Bundan sonra, ilgili öğrencinin notu da Classroom not defteri görünümleri.

Öğrenci için doğru puanın göründüğünü doğrulayın.

Tebrikler! Sonraki adıma geçmeye hazırsınız: Ek oluşturma Google Classroom'un kullanımına sunulmamıştır.